Introduction
Bulk RNA sequencing data on 24 pre-treatment breast cancer tumours
performed by Wu et al. [1] was downloaded from
GEO with accession GSE176078,
and associated
publication.
geo_id <- "GSE176078"
This dataset was sequenced using Illumina NextSeq 500 (Homo sapiens),
submitted on Apr 15 2014.
Breast cancers are clinically stratified based on:
- expression of the estrogen receptor (ER),
- expression of the progesterone receptor (PR), and
- overexpression of HER2 (or amplification of HER2
gene ERBB2)
This results in the following three clinical
subtypes within this dataset:
- Luminal ie. ER+; (ER+, PR+/-)
- HER2+; (HER2+, ER+/-, PR+/-)
- Triple Negative ie. TNBC; (ER-, PR-,
HER2-)
Breast cancers are also stratified on bulk transcriptomic profiling
via PAM50 gene signatures [2] describing five
molecular subtypes: Luminal A, Luminal B,
HER2-enriched, Basal-like, and Normal-like.
The ~70-80% concordance between clinical and molecular subtypes
motivated this study to improve functional understanding of breast
cancer in a broader and more coherent sense.
For this study, the clinical subtype conditions classified are as
follows:
HER2+ ; (HER2+, ER-,
PR+/-)
HER2+/ER+ ; (HER2+, ER+,
PR+/-)
ER+ ; (HER2-, ER+,
PR+/-)
TNBC ; (HER2-, ER-,
PR-)
The distribution of clinical subtypes across the 24 samples is shown
in table 1.
Table 1: Clinical breast cancer subtype splits in our dataset
| |
Count |
Percent |
| HER2+ |
2 |
8.33 |
| HER2+/ER+ |
2 |
8.33 |
| TNBC |
8 |
33.33 |
| ER+ |
12 |
50.00 |
| Total |
24 |
100.00 |
This leads to 16.6666667% of samples containing HER2
expression, and 41.6666667% of samples containing ER
expression, with the overlaps of these representing 8.3333333% of all
samples; 50% of those with HER2, 14.2857143% of those with
ER.
The raw counts were cleaned, mapped to HUGO Gene Nomenclature Committee
(HGNC) Symbols, and normalized to produce final counts which will be
used for the duration of this report.
Of the original 58387 genes, we were able to map and
produce 28712 unversioned, unique genes, of which filtering
outliers (keeping genes present in a minimum of 12 samples)
resulted in 14800 genes remaining. This results in the
following plots.
The density plot shows the distribution of the cleaned, filtered, and
normalized counts per million across all samples (varying colours). It
displays a smooth curve as the result of our pre-processing.
Figure 1: Density of minimum 12 samples filtered
and normalized CPM counts for 24 samples across four clinical subtypes
of breast cancer tissue
Dispersion was calculated using edgeR to describe
deviation of variance from the mean. The Biological Coefficient of
Variation (BCV) is dispersion-squared, and represents the mean-variance
relationship among genes.
Figure 2: Biological Coefficient of Variation
(Dispersion squared) for 24 samples across four clinical subtypes of
breast cancer tissue gene-wise
The normalized counts initialized above are formatted as shown by the
subsection displayed in table 2.
Table 2: Format of Normalized counts dataset as described above
| |
CID3586 |
CID3921 |
CID3941 |
CID3948 |
CID3963 |
| WASH7P |
17.5790 |
1.0450 |
14.7274 |
0.0000 |
28.5314 |
| CICP27 |
1.9276 |
3.6553 |
2.2895 |
0.0000 |
2.1353 |
| MTND2P28 |
175.8840 |
174.5844 |
168.6025 |
354.9525 |
450.4684 |
| MTATP6P1 |
413.8903 |
589.8450 |
462.3509 |
1053.1526 |
404.6456 |
| FAM87B |
2.6751 |
1.9207 |
2.7736 |
1.5650 |
2.4742 |
| LINC01128 |
26.6312 |
35.3648 |
17.6844 |
20.9555 |
21.8894 |
Differential Gene
Expression
Given our normalized expression dataset contains only grouped
classification via clinical subtypes, these are the obvious choice for
factors. But, due to the nature of these classifiers, the names
themselves represent binary pairing of HER2 and
ER expression and absence (in a clinical setting). This
provides some flexibility for analyzing differential expression since we
really have two protein expressions, with their binary pairing as the
clinical subtype classification.
The Multi-Dimensional Scaling (MDS) plot was produced using
limma on the normalized data, and it shows the distance
between samples factored by the four distinct clinical subtypes.

In the given MDS plot, notice that blue and
red are opposites (+/- and -/+),
purple is the intermediary between blue and
red (+/+), whereas green
represents TNBC: double negative (-/-).
Although progesterone is a marker for breast cancer, its expression is
not quantifiably present within the dataset, and so is not included.
However, TNBC implies PR is not overly
expressed as well.
In terms of these colours in relation to each other, you can see some
clustering appearing, although nothing is confidently distinct.
Calculate p-values
for each gene.
I redefine the model to include the clinical subtypes of breast
cancer as factors, both as four separate classifiers, and the binary
pairing of over/under expression of HER2 and
ER.
# aggregate model design
model_design <- model.matrix(~ types_df$subtype)
# split model design (binary pairs)
splt_model_design <- model.matrix(~ types_df$her2 + types_df$er)
Given both design choices, I used edgeR’s
Quasi likelihood model to create quasi-likelihood fits.
# normalized counts grouped by clinical subtype
d <- DGEList(counts=norm_matrix,
group=types_df$subtype)
# estimate dispersion on subtype model design
d_ <- estimateDisp(d, model_design)
qlfit <- glmQLFit(d_, model_design)
# in parallel, estimate dispersion on binary pairing model design
d_splt <- estimateDisp(d, splt_model_design)
qlfit_splt <- glmQLFit(d_splt, splt_model_design)
Now, we can use glmQLFTest to calculate the differential
expression according to this model.
# fit subtype model design
qlf.subtypes <- glmQLFTest(qlfit)
# fit split model design
qlf.her2p <- glmQLFTest(qlfit_splt,
coef='types_df$erTRUE')
qlf.erp <- glmQLFTest(qlfit_splt,
coef='types_df$her2TRUE')
At this point, we analyze the calculated p-values and aggregate our
top hits for each model.
# top tags for aggregate model design
top_hits <- topTags(qlf.subtypes,
sort.by = "PValue",
n = nrow(normalized_counts))
# tog tags for split model design
top_her2p <- topTags(qlf.her2p,
sort.by = "PValue",
n = nrow(normalized_counts))
top_erp <- topTags(qlf.erp,
sort.by = "PValue",
n = nrow(normalized_counts))
How many genes were
significantly differentially expressed?
For our three model designs (one aggregate, and two binary splits),
the following number of genes were significantly differentially
expressed before correction.
Table 3: Number of P-Values that are significantly differentially expressed for the three different model designs
| |
Significantly Differentially Expressed Genes |
| Aggregate across subtypes |
1462 |
| HER2 expression |
1240 |
| ER expression |
779 |
What thresholds did
you use and why?
A threshold of 0.05 for p-values is very standard. It
implies that statistically we will only achieve this outcome
5% of the time assuming the null hypothesis is true (our
null hypothesis being that there is no differential expression between
the clinical subtypes in these genes).
If I continued this analysis and found that I had a lot of genes
remaining, I could lower the threshold, but 0.05 is a solid
starting point with that in mind.
Multiple hypothesis
testing
edgeR’s analysis provides a FDR value,
which implies Benjamini-Hochberg, however I wanted to independently
verify.
corrected_top_hits <- p.adjust(top_hits$table$PValue,
method = "BH",
n = nrow(normalized_counts))
length(which(corrected_top_hits < 0.05))
[1] 3
So, using this correction method, only 3 genes pass correction for
significant differential expression.
Which method did
you use? and why?
As described, the False Discovery Rates provided by our analysis
match my independent understanding of the
Benjamini-Hochberg method.
This method is very applicable to our use-case since it is less
stringent than Bonferroni when it comes to having a large number of
hypotheses. It is best practice to use Benjamini-Hochberg first to see
which of your genes pass correction, and if you need a more stringent
corrective method, you can consider using Bonferroni. However,
Bonferroni is said to be more useful when you are testing a smaller
number of hypotheses which is generally not the case for RNA sequencing
data.
How many genes
passed correction?
For our two model designs, the following number of genes passed
correction for each classifier.
Table 4: Number of P-Values that are significantly differentially expressed for the three different model designs
| |
Significantly Differentially Expressed Genes |
Significantly Differentially Expressed Genes after correction |
| Aggregate across subtypes |
1462 |
3 |
| HER2 expression |
1240 |
0 |
| ER expression |
779 |
11 |
There is clearly a large reduction in number of genes significantly
differentially expressed.
For the aggregate model of clinical subtypes, only 3
genes passed correction for false discovery. No genes
passed correction for HER2 expression association, whereas
11 genes passed correction for ER expression
association.
The genes and their associated values are shown in the tables
below.
Amount of
differentially expressed genes
MA Plot
An MA Plot demonstrates the log-fold change in contrast to the
log-concentration for our counts. I use edgeR’s MA plot
functionality for both model designs.
edgeR::maPlot(logAbundance=top_hits$table$logCPM,
logFC=top_hits$table$logFC,
de.tags=which(top_hits$table$FDR < 0.05),
lowess=TRUE,
xlab="log(counts per million)",
ylab="log(fold-change)",
main="Figure 4: MA Plot of significantly differentially
expressed genes after correction across
clinical subtypes, aggregate design")
legend("topright", title="Significance",
legend=c("not significant",
"significant after correction"),
col=c("black", "red"), pch=1, cex=0.8)

edgeR::maPlot(logAbundance=top_erp$table$logCPM,
logFC=top_erp$table$logFC,
de.tags=which(top_erp$table$FDR < 0.05),
lowess=TRUE,
xlab="log(counts per million)",
ylab="log(fold-change)",
main="Figure 5: MA Plot of significantly differentially
expressed genes after correction
associated with ER expression")
legend("topright", title="Significance",
legend=c("not significant",
"significant after correction"),
col=c("black", "red"), pch=1, cex=0.8)

Volcano Plot
The volcano plot provides another visual for the spread of our
differentially expressed genes and their significance, both before and
after correction.
The green points are those with significant p-values before
correction, with the red points being significant genes after
correction.
plot(top_hits$table$logFC, -10*log10(top_hits$table$PValue),
main="Figure 6: Volcano Plot of significantly differentially
expressed genes after correction
across clinical subtypes, aggregate design",
xlab="log(fold change)",
ylab="-10^log(p-value)")
# highlight differentially expressed genes
points(top_hits$table$logFC[which(top_hits$table$PValue < 0.05)],
-10*log10(top_hits$table$PValue)[which(top_hits$table$PValue < 0.05)],
col="green")
points(top_hits$table$logFC[which(top_hits$table$FDR < 0.05)],
-10*log10(top_hits$table$PValue)[which(top_hits$table$FDR < 0.05)],
col="red")
legend("topleft", title="Significance",
legend=c("not significant",
"significant before correction",
"significant after correction"),
col=c("black", "green", "red"), pch=1, cex=0.8)

plot(top_erp$table$logFC, -10*log10(top_erp$table$PValue),
main="Figure 7: Volcano Plot of significantly differentially
expressed genes after correction
associated with ER expression",
xlab="log(fold change)",
ylab="-10^log(p-value)")
# highlight differentially expressed genes
points(top_erp$table$logFC[which(top_erp$table$PValue < 0.05)],
-10*log10(top_erp$table$PValue)[which(top_erp$table$PValue < 0.05)],
col="green")
points(top_erp$table$logFC[which(top_erp$table$FDR < 0.05)],
-10*log10(top_erp$table$PValue)[which(top_erp$table$FDR < 0.05)],
col="red")
legend("topleft", title="Significance",
legend=c("not significant",
"significant before correction",
"significant after correction"),
col=c("black", "green", "red"), pch=1, cex=0.8)

This volcano plot of differentially expressed genes with regards to
ER- and ER+ is very interesting given its
strong skew towards up-regulation.
plot(top_her2p$table$logFC, -10*log10(top_her2p$table$PValue),
main="Figure 8: Volcano Plot of significantly differentially
expressed genes after correction
associated with HER2 expression",
xlab="log(fold change)",
ylab="-10^log(p-value)")
# highlight differentially expressed genes
points(top_her2p$table$logFC[which(top_her2p$table$PValue < 0.05)],
-10*log10(top_her2p$table$PValue)[which(top_her2p$table$PValue < 0.05)],
col="green")
points(top_her2p$table$logFC[which(top_her2p$table$FDR < 0.05)],
-10*log10(top_her2p$table$PValue)[which(top_her2p$table$FDR < 0.05)],
col="red")
legend("topleft", title="Significance",
legend=c("not significant",
"significant before correction",
"significant after correction"),
col=c("black", "green", "red"), pch=1, cex=0.8)

Both the aggregate model design, and the HER2 design are
fairly evenly distributed around 0.
Visualizing top
hits
Heatmap
Aggregating our top hits across clinical subtypes into a heatmap, we
can see the expression visually as shown, along with a heatmap
annotation corresponding to each binary pairing represented by the
subtype classifier.
tops <- rownames(qlf.subtypes$table)[
qlf.subtypes$table$PValue < 0.05
]
top_hits_matrix = t(scale(
t(norm_matrix[which(rownames(norm_matrix) %in% tops),])
))
# colours
if (min(top_hits_matrix) == 0) {
heatmap_col = colorRamp2(c(0, max(top_hits_matrix)),
c("white", "red"))
} else {
heatmap_col = colorRamp2(c(min(top_hits_matrix), 0, max(top_hits_matrix)),
c("blue", "white", "red"))
}
# annotations
her2_col <- c("lightgreen", "red")
names(her2_col) <- c('TRUE', 'FALSE')
er_col <- c("darkgreen", "pink")
names(er_col) <- c('TRUE', 'FALSE')
types_df$her2 <- factor(types_df$her2, levels = c('TRUE','FALSE'))
types_df$er <- factor(types_df$er, levels = c('TRUE','FALSE'))
heatmap_annotation <- ComplexHeatmap::HeatmapAnnotation(
df = data.frame(her2 = types_df$her2,
er = types_df$er),
col = list(her2 = her2_col, er = er_col),
show_legend=TRUE
)
heatmap <- ComplexHeatmap::Heatmap(as.matrix(top_hits_matrix),
cluster_rows=TRUE,
cluster_columns=TRUE,
show_row_dend=TRUE,
show_column_dend=TRUE,
col=heatmap_col,
show_column_names=FALSE,
show_row_names=FALSE,
show_heatmap_legend=TRUE,
name="colour scale",
top_annotation=heatmap_annotation,
column_title="Figure 9: Heatmap of top hits across
clinical subtypes, aggregate design")

Specifically for ER overexpression or lack thereof, I
added an additional heatmap.
tops_er <- rownames(qlf.erp$table)[
qlf.erp$table$PValue < 0.05
]
tops_er_matrix = t(scale(
t(norm_matrix[which(rownames(norm_matrix) %in% tops_er),])
))
# colours
if (min(tops_er_matrix) == 0) {
heatmap_col = colorRamp2(c(0, max(tops_er_matrix)),
c("white", "red"))
} else {
heatmap_col = colorRamp2(c(min(tops_er_matrix), 0, max(tops_er_matrix)),
c("blue", "white", "red"))
}
heatmap_er <- ComplexHeatmap::Heatmap(as.matrix(tops_er_matrix),
cluster_rows=TRUE,
cluster_columns=TRUE,
show_row_dend=TRUE,
show_column_dend=TRUE,
col=heatmap_col,
show_column_names=FALSE,
show_row_names=FALSE,
show_heatmap_legend=TRUE,
name="colour scale",
top_annotation=heatmap_annotation,
column_title="Figure 10: Heatmap of top hits
associated with ER overexpression")

Do conditions
cluster together? Explain.
In figure 9, there is very visibly a cluster demonstrated between
heat intensity and ER overexpression or lack thereof with
the genes primarily in the top half being generally highly expressed in
lack of ER, and lowly expressed in overexpression of
ER. Similarly, the lower half of genes primarily follow the
opposite trend; lower expression on ER- and higher
expression on ER+.
In figure 10, it is more difficult to see the cluster patterns.
Sample 1 has very intense RNA expressions in the top half of genes, but
its matching HER2+/ER- subtype lacks this at all. This
implies the association goes in a broader scale than lack of
ER for these genes. Despite 11 genes being associated with
overexpression of ER, it does not appear to show a visible
cluster on the heatmap like the aggregate design in figure 9 does pretty
well.
Thresholded
Over-Representation Analysis
With our significantly up-regulated, and down-regulated gene-sets, we
will run a thresholded gene-set enrichment analysis.
We have 807 up-regulated genes, and 655 down-regulated genes for our
aggregate model design across all clinical subtypes.
# create non-thresholded gene sets
nt_geneset <- qlf.subtypes$table
nt_geneset[,"rank"] <- -log10(nt_geneset$PValue) * sign(nt_geneset$logFC)
nt_geneset <- nt_geneset[order(nt_geneset$rank),]
# create thresholded up and down gene sets
upreg <- rownames(nt_geneset)[which(nt_geneset$PValue < 0.05
& nt_geneset$logFC > 0)]
downreg <- rownames(nt_geneset)[which(nt_geneset$PValue < 0.05
& nt_geneset$logFC < 0)]
# function for retrieving g:GOSt from g:Profiler
gost_res <- function(query) {
res <- gost(query = query,
significant=FALSE, # set our own threshold
ordered_query = TRUE, # ordered by rank
exclude_iea=TRUE, # exclude electronic GO annotations
correction_method = "fdr", # BH
organism = "hsapiens",
source = c("REAC","WP","GO:BP",
"GO:CC", "GO:MF", "KEGG"))
return(res)
}
I query our genesets using g:Profiler’s
g:GOSt.
# up and down regulated thresholded genes
all <- gost_res(unique(c(upreg, downreg)))
# only up regulated thresholded genes
up <- gost_res(upreg)
# only down regulated thresholded genes
down <- gost_res(downreg)
Table 7: Head of thresholded up and down regulated genes from g:GOSt
| p_value |
term_id |
term_name |
| 0.018483 |
GO:0046032 |
ADP catabolic process |
| 0.018483 |
GO:0046031 |
ADP metabolic process |
| 0.018483 |
GO:0006096 |
glycolytic process |
| 0.018483 |
GO:0009057 |
macromolecule catabolic process |
| 0.018483 |
GO:0009137 |
purine nucleoside diphosphate catabolic process |
Table 8: Head of thresholded up-regulated genes from g:GOSt
| p_value |
term_id |
term_name |
| 0.0151737 |
GO:0022613 |
ribonucleoprotein complex biogenesis |
| 0.0151737 |
GO:0009179 |
purine ribonucleoside diphosphate metabolic process |
| 0.0151737 |
GO:0009181 |
purine ribonucleoside diphosphate catabolic process |
| 0.0151737 |
GO:0009056 |
catabolic process |
| 0.0151737 |
GO:0046032 |
ADP catabolic process |
Table 9: Head of thresholded down-regulated genes from g:GOSt
| p_value |
term_id |
term_name |
| 0.0666454 |
GO:0031000 |
response to caffeine |
| 0.0666454 |
GO:0071871 |
response to epinephrine |
| 0.0666454 |
GO:0071872 |
cellular response to epinephrine stimulus |
| 0.0666454 |
GO:0032989 |
cellular anatomical entity morphogenesis |
| 0.0666454 |
GO:0055006 |
cardiac cell development |
Which method did you
choose and why?
I chose to use g:Profiler with R since it was well
documented by Ruth Isserlin [3] and I had familiarity with it
through my journal entry.
g:Profiler provides an ORA
(over-representation analysis) method, and this is exactly the method I
want to perform on my thresholded data.
Which annotation data
did you use and why?
I chose the following annotation sources to get the most
comprehensive results for our functional enrichment analysis relative to
biological processes and gene ontology:
GO:BP :
Gene Ontology: Biological Processes
REAC : Reactome
WP : WikiPathways
GO:CC :
Gene Ontology: Cellular Components
GO:MF :
Gene Ontology: Molecular Function
KEGG :
Kyoto Encyclopedia of Genes and Genomes
GO:BP, REAC, and WP were
recommended by Professor Isserlin, however I ran the ORA using these and
found nothing jumped out from the resulting plots. As such, I revisited
to expand the scope of annotation sources in hopes for a more
informative result.
What version of the
annotation are you using?
For g:Profiler version information, I used:
g:Profiler version:
e112_eg59_p19_25aa4782
biomaRt version: 112
For the annotation sources selected in my query, I used:
GO:BP version annotations: BioMart classes:
releases/2024-10-27
REAC version annotations: BioMart classes:
2025-2-3
WP version 20250110
GO:CC version annotations: BioMart classes:
releases/2024-10-27
GO:MF version annotations: BioMart classes:
releases/2024-10-27
KEGG version KEGG FTP Release
2024-01-22
How many gene-sets
were returned with what thresholds?
Table 10: Gene-set sizes for different maximum thresholds with minimum intersection of 5
| |
Max 100 |
Max 250 |
Max 1000 |
Max 100000 |
| Up & Down |
991 |
1646 |
2160 |
2380 |
| Up |
558 |
1123 |
1610 |
1829 |
| Down |
126 |
324 |
570 |
643 |
Table 11: Gene-set sizes for different maximum thresholds with minimum intersection of 10
| |
Max 100 |
Max 250 |
Max 1000 |
Max 100000 |
| Up & Down |
119 |
514 |
942 |
1132 |
| Up |
49 |
314 |
698 |
886 |
| Down |
6 |
49 |
152 |
193 |
After thresholding with maximum value of 100 and minimum intersection
of 10, we can see the terms remain similar.
Table 12: Head of thresholded [3, 100] up and down-regulated genes from ORA with intersection 10
| |
term_id |
term_name |
p_value |
significant |
| 1 |
GO:0046032 |
ADP catabolic process |
0.018483 |
TRUE |
| 2 |
GO:0046031 |
ADP metabolic process |
0.018483 |
TRUE |
| 3 |
GO:0006096 |
glycolytic process |
0.018483 |
TRUE |
| 5 |
GO:0009137 |
purine nucleoside diphosphate catabolic process |
0.018483 |
TRUE |
| 6 |
GO:0019364 |
pyridine nucleotide catabolic process |
0.018483 |
TRUE |
Table 13: Head of thresholded [3, 100] up-regulated genes from ORA with intersection 10
| |
term_id |
term_name |
p_value |
significant |
| 2 |
GO:0009179 |
purine ribonucleoside diphosphate metabolic process |
0.0151737 |
TRUE |
| 3 |
GO:0009181 |
purine ribonucleoside diphosphate catabolic process |
0.0151737 |
TRUE |
| 5 |
GO:0046032 |
ADP catabolic process |
0.0151737 |
TRUE |
| 7 |
GO:0046031 |
ADP metabolic process |
0.0151737 |
TRUE |
| 8 |
GO:0006096 |
glycolytic process |
0.0151737 |
TRUE |
Table 14: Head of thresholded [3, 100] down-regulated genes from ORA with intersection 10
| |
term_id |
term_name |
p_value |
significant |
| 4 |
GO:0032989 |
cellular anatomical entity morphogenesis |
0.0666454 |
FALSE |
| 7 |
GO:0010927 |
cellular component assembly involved in morphogenesis |
0.0666454 |
FALSE |
| 48 |
GO:0035051 |
cardiocyte differentiation |
0.0676004 |
FALSE |
| 135 |
GO:0010469 |
regulation of signaling receptor activity |
0.0937527 |
FALSE |
| 4333 |
GO:0005796 |
Golgi lumen |
0.0532868 |
FALSE |
As such, we find that up-regulated genes have some significant
gene-sets after thresholding, whereas our down-regulated genes fail to
maintain significance.
Our combination table shows us strong overlap with the up-regulated
genes, further supporting the significance of our up-regulation skewed
results.
Comparing
up-regulated and down-regulated separate vs. together
The following figures demonstrate the over-representation analysis
plots for both up & down regulated, up-regulated, and down-regulated
genes respectively with only a couple of points manually
highlighted.
Figure 11: Over-representation analysis of Up
and Down regulated significantly differentially expressed genes
Figure 12: Over-representation analysis of
Up-regulated significantly differentially expressed genes
Figure 13: Over-representation analysis of
Down-regulated significantly differentially expressed genes
How do these
results compare?
Since the up-regulated gene results tend to exceed the down-regulated
gene results in terms of term significance, the combined plot appears to
more closely resemble the up-regulated plot.
In our case, ORA of up and down-regulated genes in combination did
not have a large effect on the results, but this is because the
up-regulated genes overshadow the down-regulated. If this were a
different case, we could see the difference between the up- and
down-regulated plots overshadowed and melted by the combination plot. As
such, it is important to look at both up- and down-regulated
separately.
Although, in terms of our results of this analysis, although some
terms are significant according to our arbitrary threshold, none of them
are strikingly so with maximum -log(adjusted p-values) only reaching up
to about 3 maximum, whereas plots seen with stronger functional
enrichment presence reach up much higher towards 10-16+.
Interpretation
Do the
over-representation results support conclusions or mechanisms discussed
in the original paper?
The original paper includes substantially more processing of this
data in addition to the single-cell RNA sequencing data they acquired in
tandem, so it is difficult to say whether this supports those results.
None of my significant differentially expressed genes appear throughout
the report whatsoever. The discussion and results section for the bulk
RNA-sequencing is very lackluster compared to the rest of the analysis
and results found by spatial resolution of single-cell RNA sequencing.
The RNA sequencing heatmap appears similar to mine, although they used
scaled mean interaction score and subtyped only for ER and
TNBC as opposed to the four available clinical subtypes. I
can understand this approach since the HER2 subtype
presence was relatively small compared to the rest of the samples.
There is not much functional enrichment apparently distinguishing the
classified clinical subtypes of breast cancer in this dataset; although
if we had to look at the most significant term(s), our analysis would
draw our attention to cadherin binding, ie. GO:0045296,
of which is not present in the paper’s conclusions. As such, my findings
do not support the mechanisms or conclusions discussed in the original
paper, although that does not deny my findings.
Can you find
evidence, ie. publications, to support some of the results that you see?
How does this evidence support your results?
Continuing with the most significant GO term from our
analysis–cadherin binding–there is substantial evidence that cadherins
are integral to mammary gland function, and misexpression of such leads
to increased motility and consequently greater likelihood of metastases
formation [4]. E-cadherin is one of the most
widely expressed tumour suppressors in breast cancer, however
cadherin-binding on its own is rather vague and difficult to draw
conclusions from. We can conclude, however, that cadherins are
associated with breast cancer in multiple ways, and so cadherin-binding
may be a distinguishable functional enrichment between clinical
subtypes–but this claim is too general to confidently back.
Interestingly, one of our three significantly differentially
expressed genes after correction across clinical subtypes of breast
cancer is ANXA8 which is associated with breast cancer
[5]. Rosetti et
al. suggested ANXA8 is significantly higher in
ER- subtypes as opposed to ER+ subtypes [6]
but instead of finding that in our results, we noticed
ANXA8 was significantly differentially expressed across all
clinical subtypes classified in our study and not specifically
ER overexpression or lack thereof. This warrants
investigation into why ANXA8 is expressed differentially in
ER subtypes according to research, yet selectively
expressed differentially across all four of our classified clinical
subtypes of breast cancer, and not specifically for ER
in-silico.
In terms of significantly differentially expressed genes in regards
to ER- and ER+ specifically, the most
significant gene is EPHA3 which has been shown to be
extensively more up-regulated in ER+ breast cancers [7],
which directly supports my findings. Although my findings were not
reflective of the mechanisms and direction of the paper I retrieved the
data from, they are supported by other evidence in certain ways.
In conclusion, there is some associated evidence that suggests my
results have a foundation in functional biology, however nothing has a
significance that would give me confidence to back my claim. For this, I
would want a p-value smaller than 10e-3.
Acknowledgments
This paper makes use of packages knitr [8],
BiocManager [9], GEOquery [10],
kableExtra [11], edgeR [12],
limma [13], ComplexHeatmap [14],
circlize [15], gprofiler2 [16],
GSA [17], & ggplot2 [18].
Bibliography
1. Wu SZ, Al-Eryani G, Roden DL, Junankar S, Harvey K, Andersson A, et
al. A single-cell and spatially resolved atlas of human breast cancers.
Nature genetics. 2021;53:1334–47.
2. Parker JS, Mullins M, Cheang MC, Leung S, Voduc D, Vickery T, et al.
Supervised risk predictor of breast cancer based on intrinsic subtypes.
Journal of clinical oncology. 2009;27:1160–7.
4. Derycke LD, Bracke ME. N-cadherin in the spotlight of cell-cell
adhesion, differentiation, embryogenesis, invasion and signalling.
International Journal of Developmental Biology. 2004;48:463–76.
6. Rossetti S, Bshara W, Reiners JA, Corlazzoli F, Miller A, Sacchi N.
Harnessing 3D models of mammary epithelial morphogenesis: An off the
beaten path approach to identify candidate biomarkers of early stage
breast cancer. Cancer letters. 2016;380:375–83.
7. Liang Z, Wang X, Dong K, Li X, Qin C, Zhou H. Expression pattern and
prognostic value of EPHA/EFNA in breast cancer by bioinformatics
analysis: Revealing its importance in chemotherapy. BioMed Research
International. 2021;2021:5575704.
8. Xie Y.
Dynamic documents with
R and knitr. 2nd edition. Boca Raton, Florida: Chapman;
Hall/CRC; 2015.
12. Chen Y, Lun AT, McCarthy DJ, Chen L, Baldoni P, Ritchie ME, et al.
edgeR: Empirical
analysis of digital gene expression data in r. 2025.
13. Ritchie ME, Phipson B, Wu D, Hu Y, Law CW, Shi W, et al.
limma powers differential expression analyses for
RNA-sequencing and microarray studies. Nucleic Acids
Research. 2015;43:e47.
14. Gu Z. Complex heatmap visualization. iMeta. 2022.
https://doi.org/10.1002/imt2.43.
15. Gu Z, Gu L, Eils R, Schlesner M, Brors B. Circlize implements and
enhances circular visualization in r. Bioinformatics. 2014;30:2811–2.
16. Kolberg L, Raudvere U, Kuzmin I, Vilo J, Peterson H. gprofiler2– an
r package for gene list functional enrichment analysis and namespace
conversion toolset g:profiler. F1000Research. 2020;9 (ELIXIR).
17. Efron B, Tibshirani R.
GSA: Gene set analysis.
2024.
18. Wickham H, Chang W, Henry L, Pedersen TL, Takahashi K, Wilke C, et
al.
ggplot2: Create elegant data
visualisations using the grammar of graphics. 2024.
LS0tCnRpdGxlOiAiQXNzaWdubWVudCAyIgpzdWJ0aXRsZTogIkRpZmZlcmVudGlhbCBHZW5lIEV4cHJlc3Npb24gYW5kIFByZWxpbWluYXJ5IE9SQSIKYXV0aG9yOiAiQW5uYWJlbGxhIEJyZWdhenppIgpkYXRlOiAiYHIgU3lzLkRhdGUoKWAiCm91dHB1dDogCiAgaHRtbF9ub3RlYm9vazoKICAgIHRoZW1lOiBjb3NtbwogICAgdG9jOiB5ZXMKICAgIHRvY19mbG9hdDoKICAgICAgY29sbGFwc2VkOiB0cnVlCiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIGZpZ19jYXB0aW9uOiB0cnVlCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKYmlibGlvZ3JhcGh5OiBhMl9yZWZlcmVuY2VzLmJpYgpjc2w6IGJpb21lZC1jZW50cmFsLmNzbApsaW5rLWNpdGF0aW9uczogdHJ1ZQotLS0KCmBgYHtyLCBlY2hvPUZBTFNFLCBtZXNzYWdlPUZBTFNFLCBlcnJvcj1GQUxTRSwgcmVzdWx0cz0naGlkZSd9CmxpYnJhcnkoa25pdHIpCmlmICghcmVxdWlyZSgiQmlvY01hbmFnZXIiLCBxdWlldGx5ID0gVFJVRSkpCiAgICBpbnN0YWxsLnBhY2thZ2VzKCJCaW9jTWFuYWdlciIpCgp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJHRU9xdWVyeSIpfSwgCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgeyAKICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKCJHRU9xdWVyeSIpfSwgCiAgICAgICAgIGZpbmFsbHkgPSBsaWJyYXJ5KCJHRU9xdWVyeSIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJrYWJsZUV4dHJhIil9LCAKICAgICAgICAgZXJyb3IgPSBmdW5jdGlvbihlKSB7IAogICAgICAgICAgIGluc3RhbGwucGFja2FnZXMoImthYmxlRXh0cmEiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgia2FibGVFeHRyYSIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJlZGdlUiIpfSwgCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgeyAKICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKCJlZGdlUiIpfSwgCiAgICAgICAgIGZpbmFsbHkgPSBsaWJyYXJ5KCJlZGdlUiIpKQp0cnlDYXRjaChleHByID0geyBsaWJyYXJ5KCJsaW1tYSIpfSwgCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgeyAKICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKCJsaW1tYSIpfSwgCiAgICAgICAgIGZpbmFsbHkgPSBsaWJyYXJ5KCJsaW1tYSIpKQppZiAoIXJlcXVpcmUoIkNvbXBsZXhIZWF0bWFwIiwgcXVpZXRseSA9IFRSVUUpKQogICAgQmlvY01hbmFnZXI6Omluc3RhbGwoIkNvbXBsZXhIZWF0bWFwIikKaWYgKCFyZXF1aXJlKCJjaXJjbGl6ZSIsIHF1aWV0bHkgPSBUUlVFKSkKICAgIEJpb2NNYW5hZ2VyOjppbnN0YWxsKCJjaXJjbGl6ZSIpCnRyeUNhdGNoKGV4cHIgPSB7IGxpYnJhcnkoImdwcm9maWxlcjIiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygiZ3Byb2ZpbGVyMiIpfSwgCiAgICAgICAgIGZpbmFsbHkgPSBsaWJyYXJ5KCJncHJvZmlsZXIyIikpCnRyeUNhdGNoKGV4cHIgPSB7IGxpYnJhcnkoIkdTQSIpfSwgCiAgICAgICAgIGVycm9yID0gZnVuY3Rpb24oZSkgeyAKICAgICAgICAgICBpbnN0YWxsLnBhY2thZ2VzKCJHU0EiKX0sIAogICAgICAgICBmaW5hbGx5ID0gbGlicmFyeSgiR1NBIikpCnRyeUNhdGNoKGV4cHIgPSB7IGxpYnJhcnkoImdncGxvdDIiKX0sIAogICAgICAgICBlcnJvciA9IGZ1bmN0aW9uKGUpIHsgCiAgICAgICAgICAgaW5zdGFsbC5wYWNrYWdlcygiZ2dwbG90MiIpfSwgCiAgICAgICAgIGZpbmFsbHkgPSBsaWJyYXJ5KCJnZ3Bsb3QyIikpCgpvcHRpb25zKGtuaXRyLnRhYmxlLmZvcm1hdCA9ICJodG1sIikKYGBgCgojIEludHJvZHVjdGlvbgoKQnVsayBSTkEgc2VxdWVuY2luZyBkYXRhIG9uIDI0IHByZS10cmVhdG1lbnQgYnJlYXN0IGNhbmNlciB0dW1vdXJzIHBlcmZvcm1lZCBieSBXdSBldCBhbC4gW0B3dTIwMjFzaW5nbGVdIHdhcyBkb3dubG9hZGVkIGZyb20gYEdFT2Agd2l0aCBhY2Nlc3Npb24gW0dTRTE3NjA3OF0oaHR0cHM6Ly93d3cubmNiaS5ubG0ubmloLmdvdi9nZW8vcXVlcnkvYWNjLmNnaT9hY2M9R1NFMTc2MDc4KSwgYW5kIFthc3NvY2lhdGVkIHB1YmxpY2F0aW9uXShodHRwczovL3BtYy5uY2JpLm5sbS5uaWguZ292L2FydGljbGVzL1BNQzkwNDQ4MjMvKS4KCmBgYHtyfQpnZW9faWQgPC0gIkdTRTE3NjA3OCIKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgbWVzc2FnZT1GQUxTRSwgZXJyb3I9RkFMU0UsIHJlc3VsdHM9J2hpZGUnfQpnc2UgPC0gZ2V0R0VPKGdlb19pZCwgR1NFTWF0cml4PUZBTFNFKQpncGwgPC0gbmFtZXMoZ3NlQGdwbHMpCmdwbF9pbmZvIDwtIE1ldGEoZ2V0R0VPKGdwbCkpCmBgYAoKVGhpcyBkYXRhc2V0IHdhcyBzZXF1ZW5jZWQgdXNpbmcgYHIgZ3BsX2luZm8kdGl0bGVgLCBzdWJtaXR0ZWQgb24gYHIgZ3BsX2luZm8kc3VibWlzc2lvbl9kYXRlYC4KCkJyZWFzdCBjYW5jZXJzIGFyZSBjbGluaWNhbGx5IHN0cmF0aWZpZWQgYmFzZWQgb246CgotIGV4cHJlc3Npb24gb2YgdGhlIGVzdHJvZ2VuIHJlY2VwdG9yICgqRVIqKSwgCi0gZXhwcmVzc2lvbiBvZiB0aGUgcHJvZ2VzdGVyb25lIHJlY2VwdG9yICgqUFIqKSwgYW5kCi0gb3ZlcmV4cHJlc3Npb24gb2YgKkhFUjIqIChvciBhbXBsaWZpY2F0aW9uIG9mICpIRVIyKiBnZW5lICpFUkJCMiopCgpUaGlzIHJlc3VsdHMgaW4gdGhlIGZvbGxvd2luZyB0aHJlZSBfX2NsaW5pY2FsIHN1YnR5cGVzX18gd2l0aGluIHRoaXMgZGF0YXNldDoKCi0gTHVtaW5hbCBpZS4gRVIrOyAoKkVSKyosICpQUisvLSopCi0gSEVSMis7ICgqSEVSMisqLCAqRVIrLy0qLCAqUFIrLy0qKQotIFRyaXBsZSBOZWdhdGl2ZSBpZS4gVE5CQzsgKCpFUi0qLCAqUFItKiwgKkhFUjItKikKCkJyZWFzdCBjYW5jZXJzIGFyZSBhbHNvIHN0cmF0aWZpZWQgb24gYnVsayB0cmFuc2NyaXB0b21pYyBwcm9maWxpbmcgdmlhIFBBTTUwIGdlbmUgc2lnbmF0dXJlcyBbQHBhcmtlcjIwMDlzdXBlcnZpc2VkXSBkZXNjcmliaW5nIGZpdmUgX19tb2xlY3VsYXIgc3VidHlwZXNfXzogTHVtaW5hbCBBLCBMdW1pbmFsIEIsIEhFUjItZW5yaWNoZWQsIEJhc2FsLWxpa2UsIGFuZCBOb3JtYWwtbGlrZS4KClRoZSB+NzAtODAlIGNvbmNvcmRhbmNlIGJldHdlZW4gY2xpbmljYWwgYW5kIG1vbGVjdWxhciBzdWJ0eXBlcyBtb3RpdmF0ZWQgdGhpcyBzdHVkeSB0byBpbXByb3ZlIGZ1bmN0aW9uYWwgdW5kZXJzdGFuZGluZyBvZiBicmVhc3QgY2FuY2VyIGluIGEgYnJvYWRlciBhbmQgbW9yZSBjb2hlcmVudCBzZW5zZS4KCkZvciB0aGlzIHN0dWR5LCB0aGUgY2xpbmljYWwgc3VidHlwZSBjb25kaXRpb25zIGNsYXNzaWZpZWQgYXJlIGFzIGZvbGxvd3M6CgotIGBIRVIyK2AgOyAoKkhFUjIrKiwgKkVSLSosICpQUisvLSopCi0gYEhFUjIrL0VSK2AgOyAoKkhFUjIrKiwgKkVSKyosICpQUisvLSopCi0gYEVSK2AgOyAoKkhFUjItKiwgKkVSKyosICpQUisvLSopCi0gYFROQkNgIDsgKCpIRVIyLSosICpFUi0qLCAqUFItKikKCmBgYHtyLCBtZXNzYWdlPUZBTFNFLCBlY2hvPUZBTFNFfQpub3JtYWxpemVkX2NvdW50cyA8LSByZWFkLnRhYmxlKAogIGZpbGU9ZmlsZS5wYXRoKGdldHdkKCksIGdlb19pZCwKICAgICAgICAgICAgICAgICBwYXN0ZShnZW9faWQsIAogICAgICAgICAgICAgICAgICAgICAgICJub3JtYWxpemVkX2NvdW50cy50eHQiLCAKICAgICAgICAgICAgICAgICAgICAgICBzZXA9Il8iKSksCiAgaGVhZGVyPVRSVUUsIHNlcD0iXHQiLCAKICBzdHJpbmdzQXNGYWN0b3JzPUZBTFNFLCAKICBjaGVjay5uYW1lcz1GQUxTRSkKYGBgCgpUaGUgZGlzdHJpYnV0aW9uIG9mIGNsaW5pY2FsIHN1YnR5cGVzIGFjcm9zcyB0aGUgMjQgc2FtcGxlcyBpcyBzaG93biBpbiB0YWJsZSAxLgoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KdHlwZXMgPC0gZG8uY2FsbChyYmluZCwKICAgICAgICAgICAgICAgICBsYXBwbHkoZ3NlQGdzbXMsLAogICAgICAgICAgICAgICAgICAgICAgICBGVU49ZnVuY3Rpb24oeCwgLi4uKXsKICAgICAgICAgICAgICAgICAgICAgICAgICBjKHhAaGVhZGVyJHRpdGxlLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgeEBoZWFkZXIkY2hhcmFjdGVyaXN0aWNzX2NoMSl9KSlbLGMoMSwyKV0KdHlwZXNbLDJdIDwtIGdzdWIodHlwZXNbLDJdLAogICAgICAgICAgICAgICAgICBwYXR0ZXJuID0gImNsaW5pY2FsX3N1YnR5cGU6ICIsCiAgICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50ID0gIiIpCgpwcmVzZW50IDwtIGNvbG5hbWVzKG5vcm1hbGl6ZWRfY291bnRzKQp0eXBlcyA8LSB0eXBlc1t3aGljaCh0eXBlc1ssMV0gJWluJSBwcmVzZW50KSxdCgp0eXBlcyA8LSBjYmluZCh0eXBlcywgZ3JlcGwoIl5bSF1bRV1bUl1bMl1bK10iLCB0eXBlc1ssMl0pKQp0eXBlcyA8LSBjYmluZCh0eXBlcywgZ3JlcGwoIltFXVtSXVsrXSQiLCB0eXBlc1ssMl0pKQpjb2xuYW1lcyh0eXBlcykgPC0gYygic2FtcGxlIiwgInN1YnR5cGUiLCAiaGVyMiIsICJlciIpCnR5cGVzX2RmIDwtIGFzLmRhdGEuZnJhbWUodHlwZXMpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIG1lc3NhZ2U9RkFMU0UsIGVycm9yPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KaGVyMiA9IGxlbmd0aCh3aGljaCh0eXBlc1ssInN1YnR5cGUiXSA9PSAiSEVSMisiKSkKaGVyMmVyID0gbGVuZ3RoKHdoaWNoKHR5cGVzWywic3VidHlwZSJdID09ICJIRVIyKy9FUisiKSkKdG5iYyA9IGxlbmd0aCh3aGljaCh0eXBlc1ssInN1YnR5cGUiXSA9PSAiVE5CQyIpKQplciA9IGxlbmd0aCh3aGljaCh0eXBlc1ssInN1YnR5cGUiXSA9PSAiRVIrIikpCnRvdGFsID0gc3VtKGhlcjIsIGhlcjJlciwgdG5iYywgZXIpCgpzdWJ0eXBlX2NvdW50cyA9IGRhdGEuZnJhbWUoYyhoZXIyLCBoZXIyZXIsIHRuYmMsIGVyLCB0b3RhbCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3cubmFtZXMgPSBjKCJIRVIyKyIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiSEVSMisvRVIrIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJUTkJDIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJFUisiLCAiVG90YWwiKSkKc3VidHlwZV9jb3VudHMkcGVyY2VudGFnZXMgPSBzdWJ0eXBlX2NvdW50c1ssMV0gKiAxMDAgLyB0b3RhbApgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdhc2lzJ30Kc3VidHlwZV9jb3VudHMgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDE6IENsaW5pY2FsIGJyZWFzdCBjYW5jZXIgc3VidHlwZSBzcGxpdHMgaW4gb3VyIGRhdGFzZXQiLCAKICAgICAgZGlnaXRzPTIsCiAgICAgIGNvbC5uYW1lcz1jKCJDb3VudCIsICJQZXJjZW50IikpICU+JQogIGthYmxlX3N0eWxpbmcoKSAlPiUKICByb3dfc3BlYyg1LCBib2xkID0gVCkKYGBgCgpUaGlzIGxlYWRzIHRvIGByIDQwMC8yNGAlIG9mIHNhbXBsZXMgY29udGFpbmluZyBgSEVSMmAgZXhwcmVzc2lvbiwgYW5kIGByIDEwMDAvMjRgJSBvZiBzYW1wbGVzIGNvbnRhaW5pbmcgYEVSYCBleHByZXNzaW9uLCB3aXRoIHRoZSBvdmVybGFwcyBvZiB0aGVzZSByZXByZXNlbnRpbmcgYHIgMjAwLzI0YCUgb2YgYWxsIHNhbXBsZXM7IGByIDIwMC80YCUgb2YgdGhvc2Ugd2l0aCBgSEVSMmAsIGByIDIwMC8xNGAlIG9mIHRob3NlIHdpdGggYEVSYC4KClRoZSByYXcgY291bnRzIHdlcmUgY2xlYW5lZCwgbWFwcGVkIHRvIFtIVUdPIEdlbmUgTm9tZW5jbGF0dXJlIENvbW1pdHRlZSAoSEdOQykgU3ltYm9sc10oaHR0cHM6Ly93d3cuZ2VuZW5hbWVzLm9yZy8pLCBhbmQgbm9ybWFsaXplZCB0byBwcm9kdWNlIGZpbmFsIGNvdW50cyB3aGljaCB3aWxsIGJlIHVzZWQgZm9yIHRoZSBkdXJhdGlvbiBvZiB0aGlzIHJlcG9ydC4KCk9mIHRoZSBvcmlnaW5hbCBgNTgzODdgIGdlbmVzLCB3ZSB3ZXJlIGFibGUgdG8gbWFwIGFuZCBwcm9kdWNlIGAyODcxMmAgdW52ZXJzaW9uZWQsIHVuaXF1ZSBnZW5lcywgb2Ygd2hpY2ggZmlsdGVyaW5nIG91dGxpZXJzIChrZWVwaW5nIGdlbmVzIHByZXNlbnQgaW4gYSBtaW5pbXVtIG9mIGAxMmAgc2FtcGxlcykgcmVzdWx0ZWQgaW4gYDE0ODAwYCBnZW5lcyByZW1haW5pbmcuIFRoaXMgcmVzdWx0cyBpbiB0aGUgZm9sbG93aW5nIHBsb3RzLgoKVGhlIGRlbnNpdHkgcGxvdCBzaG93cyB0aGUgZGlzdHJpYnV0aW9uIG9mIHRoZSBjbGVhbmVkLCBmaWx0ZXJlZCwgYW5kIG5vcm1hbGl6ZWQgY291bnRzIHBlciBtaWxsaW9uIGFjcm9zcyBhbGwgc2FtcGxlcyAodmFyeWluZyBjb2xvdXJzKS4gSXQgZGlzcGxheXMgYSBzbW9vdGggY3VydmUgYXMgdGhlIHJlc3VsdCBvZiBvdXIgcHJlLXByb2Nlc3NpbmcuCgo8YnIvPgoKIVtGaWd1cmUgMTogRGVuc2l0eSBvZiBtaW5pbXVtIDEyIHNhbXBsZXMgZmlsdGVyZWQgYW5kIG5vcm1hbGl6ZWQgQ1BNIGNvdW50cyBmb3IgMjQgc2FtcGxlcyBhY3Jvc3MgZm91ciBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIHRpc3N1ZV0oL2hvbWUvcnN0dWRpby9wcm9qZWN0cy9maWd1cmVzL0dTRTE3NjA3OF9maWx0X25vcm1fZGVuc2l0eS5wbmcpCgo8YnIvPgpEaXNwZXJzaW9uIHdhcyBjYWxjdWxhdGVkIHVzaW5nIGBlZGdlUmAgdG8gZGVzY3JpYmUgZGV2aWF0aW9uIG9mIHZhcmlhbmNlIGZyb20gdGhlIG1lYW4uIFRoZSBCaW9sb2dpY2FsIENvZWZmaWNpZW50IG9mIFZhcmlhdGlvbiAoQkNWKSBpcyBkaXNwZXJzaW9uLXNxdWFyZWQsIGFuZCByZXByZXNlbnRzIHRoZSBtZWFuLXZhcmlhbmNlIHJlbGF0aW9uc2hpcCBhbW9uZyBnZW5lcy4KCiFbRmlndXJlIDI6IEJpb2xvZ2ljYWwgQ29lZmZpY2llbnQgb2YgVmFyaWF0aW9uIChEaXNwZXJzaW9uIHNxdWFyZWQpIGZvciAyNCBzYW1wbGVzIGFjcm9zcyBmb3VyIGNsaW5pY2FsIHN1YnR5cGVzIG9mIGJyZWFzdCBjYW5jZXIgdGlzc3VlIGdlbmUtd2lzZV0oL2hvbWUvcnN0dWRpby9wcm9qZWN0cy9maWd1cmVzL0dTRTE3NjA3OF9iY3YucG5nKQoKPGJyLz4KClRoZSBub3JtYWxpemVkIGNvdW50cyBpbml0aWFsaXplZCBhYm92ZSBhcmUgZm9ybWF0dGVkIGFzIHNob3duIGJ5IHRoZSBzdWJzZWN0aW9uIGRpc3BsYXllZCBpbiB0YWJsZSAyLgoKYGBge3IsIGVjaG89RkFMU0UsIHJlc3VsdHM9J2FzaXMnfQpoZWFkKG5vcm1hbGl6ZWRfY291bnRzWzE6NV0pICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSAyOiBGb3JtYXQgb2YgTm9ybWFsaXplZCBjb3VudHMgZGF0YXNldCBhcyBkZXNjcmliZWQgYWJvdmUiLCBkaWdpdHM9NCkgJT4lCiAga2FibGVfc3R5bGluZygpCmBgYAoKIyBEaWZmZXJlbnRpYWwgR2VuZSBFeHByZXNzaW9uCgpHaXZlbiBvdXIgbm9ybWFsaXplZCBleHByZXNzaW9uIGRhdGFzZXQgY29udGFpbnMgb25seSBncm91cGVkIGNsYXNzaWZpY2F0aW9uIHZpYSBjbGluaWNhbCBzdWJ0eXBlcywgdGhlc2UgYXJlIHRoZSBvYnZpb3VzIGNob2ljZSBmb3IgZmFjdG9ycy4gQnV0LCBkdWUgdG8gdGhlIG5hdHVyZSBvZiB0aGVzZSBjbGFzc2lmaWVycywgdGhlIG5hbWVzIHRoZW1zZWx2ZXMgcmVwcmVzZW50IGJpbmFyeSBwYWlyaW5nIG9mIGBIRVIyYCBhbmQgYEVSYCBleHByZXNzaW9uIGFuZCBhYnNlbmNlIChpbiBhIGNsaW5pY2FsIHNldHRpbmcpLiBUaGlzIHByb3ZpZGVzIHNvbWUgZmxleGliaWxpdHkgZm9yIGFuYWx5emluZyBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBzaW5jZSB3ZSByZWFsbHkgaGF2ZSB0d28gcHJvdGVpbiBleHByZXNzaW9ucywgd2l0aCB0aGVpciBiaW5hcnkgcGFpcmluZyBhcyB0aGUgY2xpbmljYWwgc3VidHlwZSBjbGFzc2lmaWNhdGlvbi4KClRoZSBNdWx0aS1EaW1lbnNpb25hbCBTY2FsaW5nIChNRFMpIHBsb3Qgd2FzIHByb2R1Y2VkIHVzaW5nIGBsaW1tYWAgb24gdGhlIG5vcm1hbGl6ZWQgZGF0YSwgYW5kIGl0IHNob3dzIHRoZSBkaXN0YW5jZSBiZXR3ZWVuIHNhbXBsZXMgZmFjdG9yZWQgYnkgdGhlIGZvdXIgZGlzdGluY3QgY2xpbmljYWwgc3VidHlwZXMuCjxici8+CgpgYGB7ciBtZHMtc3VidHlwZSwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD01LCBmaWcuY2FwPSJGaWd1cmUgMzogTXVsdGktRGltZW5zaW9uYWwgU2NhbGluZyBwbG90IGZvciBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIGFzIGNsYXNzaWZpY2F0aW9ucyBvZiBvdmVyZXhwcmVzc2lvbiwgb3IgbGFjayB0aGVyZW9mLCBvZiBFUiBhbmQgSEVSMiJ9Cm5vcm1fbWF0cml4IDwtIGFzLm1hdHJpeChub3JtYWxpemVkX2NvdW50cykKCmxpbW1hOjpwbG90TURTKG5vcm1fbWF0cml4LCBsYWJlbHM9TlVMTCwgcGNoPTEsCiAgICAgICAgICAgICAgIGNvbCA9IGMoImJsdWUiLCAicmVkIiwgCiAgICAgICAgICAgICAgICAgICAgICAgInB1cnBsZSIsICJncmVlbiIpW2ZhY3Rvcih0eXBlc19kZiRzdWJ0eXBlKV0pCnRpdGxlKCJGaWd1cmUgMzogTURTIHBsb3Qgb2YgY2xpbmljYWwgc3VidHlwZXMgb2YgYnJlYXN0IGNhbmNlciIpCmxlZ2VuZCgidG9wbGVmdCIsCiAgICAgICBsZWdlbmQ9bGV2ZWxzKGZhY3Rvcih0eXBlc19kZiRzdWJ0eXBlKSksCiAgICAgICBwY2g9YygxKSwgY29sPWMoImJsdWUiLCAicmVkIiwgInB1cnBsZSIsICJncmVlbiIpLAogICAgICAgdGl0bGUgPSAiQ2xpbmljYWwgc3VidHlwZSIsIGJ0eT0nbicsIGNleD0wLjc1KQpgYGAKCgpJbiB0aGUgZ2l2ZW4gTURTIHBsb3QsIG5vdGljZSB0aGF0IGBibHVlYCBhbmQgYHJlZGAgYXJlIG9wcG9zaXRlcyAoYCsvLWAgYW5kIGAtLytgKSwgYHB1cnBsZWAgaXMgdGhlIGludGVybWVkaWFyeSBiZXR3ZWVuIGBibHVlYCBhbmQgYHJlZGAgKGArLytgKSwgd2hlcmVhcyBgZ3JlZW5gIHJlcHJlc2VudHMgYFROQkNgOiBkb3VibGUgbmVnYXRpdmUgKGAtLy1gKS4gQWx0aG91Z2ggcHJvZ2VzdGVyb25lIGlzIGEgbWFya2VyIGZvciBicmVhc3QgY2FuY2VyLCBpdHMgZXhwcmVzc2lvbiBpcyBub3QgcXVhbnRpZmlhYmx5IHByZXNlbnQgd2l0aGluIHRoZSBkYXRhc2V0LCBhbmQgc28gaXMgbm90IGluY2x1ZGVkLiBIb3dldmVyLCBgVE5CQ2AgaW1wbGllcyBgUFJgIGlzIG5vdCBvdmVybHkgZXhwcmVzc2VkIGFzIHdlbGwuCgpJbiB0ZXJtcyBvZiB0aGVzZSBjb2xvdXJzIGluIHJlbGF0aW9uIHRvIGVhY2ggb3RoZXIsIHlvdSBjYW4gc2VlIHNvbWUgY2x1c3RlcmluZyBhcHBlYXJpbmcsIGFsdGhvdWdoIG5vdGhpbmcgaXMgY29uZmlkZW50bHkgZGlzdGluY3QuCgojIyBDYWxjdWxhdGUgcC12YWx1ZXMgZm9yIGVhY2ggZ2VuZS4gCgpJIHJlZGVmaW5lIHRoZSBtb2RlbCB0byBpbmNsdWRlIHRoZSBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIGFzIGZhY3RvcnMsIGJvdGggYXMgZm91ciBzZXBhcmF0ZSBjbGFzc2lmaWVycywgYW5kIHRoZSBiaW5hcnkgcGFpcmluZyBvZiBvdmVyL3VuZGVyIGV4cHJlc3Npb24gb2YgYEhFUjJgIGFuZCBgRVJgLgoKYGBge3J9CiMgYWdncmVnYXRlIG1vZGVsIGRlc2lnbgptb2RlbF9kZXNpZ24gPC0gbW9kZWwubWF0cml4KH4gdHlwZXNfZGYkc3VidHlwZSkKCiMgc3BsaXQgbW9kZWwgZGVzaWduIChiaW5hcnkgcGFpcnMpCnNwbHRfbW9kZWxfZGVzaWduIDwtIG1vZGVsLm1hdHJpeCh+IHR5cGVzX2RmJGhlcjIgKyB0eXBlc19kZiRlcikKYGBgCgpHaXZlbiBib3RoIGRlc2lnbiBjaG9pY2VzLCBJIHVzZWQgYGVkZ2VSYCdzIGBRdWFzaSBsaWtlbGlob29kIG1vZGVsYCB0byBjcmVhdGUgcXVhc2ktbGlrZWxpaG9vZCBmaXRzLgoKYGBge3J9CiMgbm9ybWFsaXplZCBjb3VudHMgZ3JvdXBlZCBieSBjbGluaWNhbCBzdWJ0eXBlCmQgPC0gREdFTGlzdChjb3VudHM9bm9ybV9tYXRyaXgsIAogICAgICAgICAgICAgZ3JvdXA9dHlwZXNfZGYkc3VidHlwZSkKCiMgZXN0aW1hdGUgZGlzcGVyc2lvbiBvbiBzdWJ0eXBlIG1vZGVsIGRlc2lnbgpkXyA8LSBlc3RpbWF0ZURpc3AoZCwgbW9kZWxfZGVzaWduKQpxbGZpdCA8LSBnbG1RTEZpdChkXywgbW9kZWxfZGVzaWduKQoKIyBpbiBwYXJhbGxlbCwgZXN0aW1hdGUgZGlzcGVyc2lvbiBvbiBiaW5hcnkgcGFpcmluZyBtb2RlbCBkZXNpZ24KZF9zcGx0IDwtIGVzdGltYXRlRGlzcChkLCBzcGx0X21vZGVsX2Rlc2lnbikKcWxmaXRfc3BsdCA8LSBnbG1RTEZpdChkX3NwbHQsIHNwbHRfbW9kZWxfZGVzaWduKQpgYGAKCk5vdywgd2UgY2FuIHVzZSBgZ2xtUUxGVGVzdGAgdG8gY2FsY3VsYXRlIHRoZSBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbiBhY2NvcmRpbmcgdG8gdGhpcyBtb2RlbC4KCmBgYHtyfQojIGZpdCBzdWJ0eXBlIG1vZGVsIGRlc2lnbgpxbGYuc3VidHlwZXMgPC0gZ2xtUUxGVGVzdChxbGZpdCkKYGBgCgpgYGB7cn0KIyBmaXQgc3BsaXQgbW9kZWwgZGVzaWduCnFsZi5oZXIycCA8LSBnbG1RTEZUZXN0KHFsZml0X3NwbHQsIAogICAgICAgICAgICAgICAgICAgICAgICBjb2VmPSd0eXBlc19kZiRlclRSVUUnKQpxbGYuZXJwIDwtIGdsbVFMRlRlc3QocWxmaXRfc3BsdCwgCiAgICAgICAgICAgICAgICAgICAgICBjb2VmPSd0eXBlc19kZiRoZXIyVFJVRScpCmBgYAoKQXQgdGhpcyBwb2ludCwgd2UgYW5hbHl6ZSB0aGUgY2FsY3VsYXRlZCBwLXZhbHVlcyBhbmQgYWdncmVnYXRlIG91ciB0b3AgaGl0cyBmb3IgZWFjaCBtb2RlbC4KCmBgYHtyfQojIHRvcCB0YWdzIGZvciBhZ2dyZWdhdGUgbW9kZWwgZGVzaWduCnRvcF9oaXRzIDwtIHRvcFRhZ3MocWxmLnN1YnR5cGVzLCAKICAgICAgICAgICAgICAgICAgICBzb3J0LmJ5ID0gIlBWYWx1ZSIsCiAgICAgICAgICAgICAgICAgICAgbiA9IG5yb3cobm9ybWFsaXplZF9jb3VudHMpKQoKIyB0b2cgdGFncyBmb3Igc3BsaXQgbW9kZWwgZGVzaWduCnRvcF9oZXIycCA8LSB0b3BUYWdzKHFsZi5oZXIycCwKICAgICAgICAgICAgICAgICAgICAgc29ydC5ieSA9ICJQVmFsdWUiLAogICAgICAgICAgICAgICAgICAgICBuID0gbnJvdyhub3JtYWxpemVkX2NvdW50cykpCnRvcF9lcnAgPC0gdG9wVGFncyhxbGYuZXJwLAogICAgICAgICAgICAgICAgICAgc29ydC5ieSA9ICJQVmFsdWUiLAogICAgICAgICAgICAgICAgICAgbiA9IG5yb3cobm9ybWFsaXplZF9jb3VudHMpKQpgYGAKCiMjIyBIb3cgbWFueSBnZW5lcyB3ZXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkPwoKYGBge3IsIGVjaG89RkFMU0V9CiMgbGVuZ3RoKHdoaWNoKHRvcF9oaXRzJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKQojIGxlbmd0aCh3aGljaCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlIDwgMC4wNSkpCiMgbGVuZ3RoKHdoaWNoKHRvcF9wZXJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKQpgYGAKCkZvciBvdXIgdGhyZWUgbW9kZWwgZGVzaWducyAob25lIGFnZ3JlZ2F0ZSwgYW5kIHR3byBiaW5hcnkgc3BsaXRzKSwgdGhlIGZvbGxvd2luZyBudW1iZXIgb2YgZ2VuZXMgd2VyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBiZWZvcmUgY29ycmVjdGlvbi4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSJUYWJsZSAzOiBOdW1iZXIgb2YgUC1WYWx1ZXMgdGhhdCBhcmUgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQsIGllLiA8IDAuMDUsIGZvciB0aGUgdGhyZWUgZGlmZmVyZW50IG1vZGVsIGRlc2lnbnMifQpwdmFsc19kZiA8LSBkYXRhLmZyYW1lKAogIGMobGVuZ3RoKHdoaWNoKHRvcF9oaXRzJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKSwKICAgIGxlbmd0aCh3aGljaCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlIDwgMC4wNSkpLAogICAgbGVuZ3RoKHdoaWNoKHRvcF9lcnAkdGFibGUkUFZhbHVlIDwgMC4wNSkpKSwKICByb3cubmFtZXMgPSBjKCJBZ2dyZWdhdGUgYWNyb3NzIHN1YnR5cGVzIiwgIkhFUjIgZXhwcmVzc2lvbiIsICJFUiBleHByZXNzaW9uIikKKQoKcHZhbHNfZGYgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDM6IE51bWJlciBvZiBQLVZhbHVlcyB0aGF0IGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBmb3IgdGhlIHRocmVlIGRpZmZlcmVudCBtb2RlbCBkZXNpZ25zIiwKICAgICAgICAgICAgICAgY29sLm5hbWVzPWMoIlNpZ25pZmljYW50bHkgRGlmZmVyZW50aWFsbHkgRXhwcmVzc2VkIEdlbmVzIikpICU+JQogIGthYmxlX3N0eWxpbmcoKQpgYGAKCiMjIyBXaGF0IHRocmVzaG9sZHMgZGlkIHlvdSB1c2UgYW5kIHdoeT8KCkEgdGhyZXNob2xkIG9mIGAwLjA1YCBmb3IgcC12YWx1ZXMgaXMgdmVyeSBzdGFuZGFyZC4gSXQgaW1wbGllcyB0aGF0IHN0YXRpc3RpY2FsbHkgd2Ugd2lsbCBvbmx5IGFjaGlldmUgdGhpcyBvdXRjb21lIGA1YCUgb2YgdGhlIHRpbWUgYXNzdW1pbmcgdGhlIG51bGwgaHlwb3RoZXNpcyBpcyB0cnVlIChvdXIgbnVsbCBoeXBvdGhlc2lzIGJlaW5nIHRoYXQgdGhlcmUgaXMgbm8gZGlmZmVyZW50aWFsIGV4cHJlc3Npb24gYmV0d2VlbiB0aGUgY2xpbmljYWwgc3VidHlwZXMgaW4gdGhlc2UgZ2VuZXMpLgoKSWYgSSBjb250aW51ZWQgdGhpcyBhbmFseXNpcyBhbmQgZm91bmQgdGhhdCBJIGhhZCBhIGxvdCBvZiBnZW5lcyByZW1haW5pbmcsIEkgY291bGQgbG93ZXIgdGhlIHRocmVzaG9sZCwgYnV0IGAwLjA1YCBpcyBhIHNvbGlkIHN0YXJ0aW5nIHBvaW50IHdpdGggdGhhdCBpbiBtaW5kLgoKIyMgTXVsdGlwbGUgaHlwb3RoZXNpcyB0ZXN0aW5nCgpgZWRnZVJgJ3MgYW5hbHlzaXMgcHJvdmlkZXMgYSBgRkRSYCB2YWx1ZSwgd2hpY2ggaW1wbGllcyBCZW5qYW1pbmktSG9jaGJlcmcsIGhvd2V2ZXIgSSB3YW50ZWQgdG8gaW5kZXBlbmRlbnRseSB2ZXJpZnkuCgpgYGB7cn0KY29ycmVjdGVkX3RvcF9oaXRzIDwtIHAuYWRqdXN0KHRvcF9oaXRzJHRhYmxlJFBWYWx1ZSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtZXRob2QgPSAiQkgiLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG4gPSBucm93KG5vcm1hbGl6ZWRfY291bnRzKSkKbGVuZ3RoKHdoaWNoKGNvcnJlY3RlZF90b3BfaGl0cyA8IDAuMDUpKQpgYGAKClNvLCB1c2luZyB0aGlzIGNvcnJlY3Rpb24gbWV0aG9kLCBvbmx5IDMgZ2VuZXMgcGFzcyBjb3JyZWN0aW9uIGZvciBzaWduaWZpY2FudCBkaWZmZXJlbnRpYWwgZXhwcmVzc2lvbi4KCiMjIyBXaGljaCBtZXRob2QgZGlkIHlvdSB1c2U/IGFuZCB3aHk/CgpBcyBkZXNjcmliZWQsIHRoZSBGYWxzZSBEaXNjb3ZlcnkgUmF0ZXMgcHJvdmlkZWQgYnkgb3VyIGFuYWx5c2lzIG1hdGNoIG15IGluZGVwZW5kZW50IHVuZGVyc3RhbmRpbmcgb2YgdGhlIF9fQmVuamFtaW5pLUhvY2hiZXJnX18gbWV0aG9kLiAKClRoaXMgbWV0aG9kIGlzIHZlcnkgYXBwbGljYWJsZSB0byBvdXIgdXNlLWNhc2Ugc2luY2UgaXQgaXMgbGVzcyBzdHJpbmdlbnQgdGhhbiBCb25mZXJyb25pIHdoZW4gaXQgY29tZXMgdG8gaGF2aW5nIGEgbGFyZ2UgbnVtYmVyIG9mIGh5cG90aGVzZXMuIEl0IGlzIGJlc3QgcHJhY3RpY2UgdG8gdXNlIEJlbmphbWluaS1Ib2NoYmVyZyBmaXJzdCB0byBzZWUgd2hpY2ggb2YgeW91ciBnZW5lcyBwYXNzIGNvcnJlY3Rpb24sIGFuZCBpZiB5b3UgbmVlZCBhIG1vcmUgc3RyaW5nZW50IGNvcnJlY3RpdmUgbWV0aG9kLCB5b3UgY2FuIGNvbnNpZGVyIHVzaW5nIEJvbmZlcnJvbmkuIEhvd2V2ZXIsIEJvbmZlcnJvbmkgaXMgc2FpZCB0byBiZSBtb3JlIHVzZWZ1bCB3aGVuIHlvdSBhcmUgdGVzdGluZyBhIHNtYWxsZXIgbnVtYmVyIG9mIGh5cG90aGVzZXMgd2hpY2ggaXMgZ2VuZXJhbGx5IG5vdCB0aGUgY2FzZSBmb3IgUk5BIHNlcXVlbmNpbmcgZGF0YS4KCiMjIyBIb3cgbWFueSBnZW5lcyBwYXNzZWQgY29ycmVjdGlvbj8KCkZvciBvdXIgdHdvIG1vZGVsIGRlc2lnbnMsIHRoZSBmb2xsb3dpbmcgbnVtYmVyIG9mIGdlbmVzIHBhc3NlZCBjb3JyZWN0aW9uIGZvciBlYWNoIGNsYXNzaWZpZXIuCgpgYGB7ciwgZWNobz1GQUxTRX0KIyBsZW5ndGgod2hpY2godG9wX2hpdHMkdGFibGUkRkRSIDwgMC4wNSkpCiMgbGVuZ3RoKHdoaWNoKHRvcF9oZXIycCR0YWJsZSRGRFIgPCAwLjA1KSkKIyBsZW5ndGgod2hpY2godG9wX2VycCR0YWJsZSRGRFIgPCAwLjA1KSkKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmNhcD0iVGFibGUgNDogTnVtYmVyIG9mIFAtVmFsdWVzIHRoYXQgYXJlIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkLCBpZS4gPCAwLjA1LCBiZWZvcmUgYW5kIGFmdGVyIEJlbmphbWluaS1Ib2NoYmVyZyBjb3JyZWN0aW9uIGZvciB0aGUgdGhyZWUgZGlmZmVyZW50IG1vZGVsIGRlc2lnbnMifQpwdmFsc19kZiA8LSBkYXRhLmZyYW1lKAogIGMobGVuZ3RoKHdoaWNoKHRvcF9oaXRzJHRhYmxlJFBWYWx1ZSA8IDAuMDUpKSwKICAgIGxlbmd0aCh3aGljaCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlIDwgMC4wNSkpLAogICAgbGVuZ3RoKHdoaWNoKHRvcF9lcnAkdGFibGUkUFZhbHVlIDwgMC4wNSkpKSwKICByb3cubmFtZXMgPSBjKCJBZ2dyZWdhdGUgYWNyb3NzIHN1YnR5cGVzIiwgIkhFUjIgZXhwcmVzc2lvbiIsICJFUiBleHByZXNzaW9uIikKKQpwdmFsc19kZiA8LSBjYmluZChwdmFsc19kZiwgCiAgICAgICAgICAgICAgICAgIGMobGVuZ3RoKHdoaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpKSwKICAgICAgICAgICAgICAgICAgICBsZW5ndGgod2hpY2godG9wX2hlcjJwJHRhYmxlJEZEUiA8IDAuMDUpKSwKICAgICAgICAgICAgICAgICAgICBsZW5ndGgod2hpY2godG9wX2VycCR0YWJsZSRGRFIgPCAwLjA1KSkpKQoKcHZhbHNfZGYgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDQ6IE51bWJlciBvZiBQLVZhbHVlcyB0aGF0IGFyZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBmb3IgdGhlIHRocmVlIGRpZmZlcmVudCBtb2RlbCBkZXNpZ25zIiwKICAgICAgICAgICAgICAgY29sLm5hbWVzPWMoIlNpZ25pZmljYW50bHkgRGlmZmVyZW50aWFsbHkgRXhwcmVzc2VkIEdlbmVzIiwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJTaWduaWZpY2FudGx5IERpZmZlcmVudGlhbGx5IEV4cHJlc3NlZCBHZW5lcyBhZnRlciBjb3JyZWN0aW9uIikpICU+JQogIGthYmxlX3N0eWxpbmcoKQpgYGAKClRoZXJlIGlzIGNsZWFybHkgYSBsYXJnZSByZWR1Y3Rpb24gaW4gbnVtYmVyIG9mIGdlbmVzIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkLgoKRm9yIHRoZSBhZ2dyZWdhdGUgbW9kZWwgb2YgY2xpbmljYWwgc3VidHlwZXMsIG9ubHkgYDNgIGdlbmVzIHBhc3NlZCBjb3JyZWN0aW9uIGZvciBmYWxzZSBkaXNjb3ZlcnkuIF9fTm9fXyBnZW5lcyBwYXNzZWQgY29ycmVjdGlvbiBmb3IgYEhFUjJgIGV4cHJlc3Npb24gYXNzb2NpYXRpb24sIHdoZXJlYXMgYDExYCBnZW5lcyBwYXNzZWQgY29ycmVjdGlvbiBmb3IgYEVSYCBleHByZXNzaW9uIGFzc29jaWF0aW9uLgoKVGhlIGdlbmVzIGFuZCB0aGVpciBhc3NvY2lhdGVkIHZhbHVlcyBhcmUgc2hvd24gaW4gdGhlIHRhYmxlcyBiZWxvdy4KCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSJUYWJsZSA1OiBHZW5lcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBhZnRlciBjb3JyZWN0aW9uIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcywgYWdncmVnYXRlIGRlc2lnbiJ9CnRvcF9oaXRzJHRhYmxlW3RvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUsXQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuY2FwPSJUYWJsZSA2OiBHZW5lcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBhZnRlciBjb3JyZWN0aW9uIGFzc29jaWF0ZWQgd2l0aCBFUiBvdmVyZXhwcmVzc2lvbiJ9CnRvcF9lcnAkdGFibGVbdG9wX2VycCR0YWJsZSRGRFIgPCAwLjA1LF0KYGBgCgojIyBBbW91bnQgb2YgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCgojIyMgTUEgUGxvdAoKQW4gTUEgUGxvdCBkZW1vbnN0cmF0ZXMgdGhlIGxvZy1mb2xkIGNoYW5nZSBpbiBjb250cmFzdCB0byB0aGUgbG9nLWNvbmNlbnRyYXRpb24gZm9yIG91ciBjb3VudHMuIEkgdXNlIGBlZGdlUmAncyBNQSBwbG90IGZ1bmN0aW9uYWxpdHkgZm9yIGJvdGggbW9kZWwgZGVzaWducy4KCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy5jYXA9IkZpZ3VyZSA0OiBNQSBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gYWNyb3NzIGNsaW5pY2FsIHN1YnR5cGVzLCBhZ2dyZWdhdGUgZGVzaWduIn0KZWRnZVI6Om1hUGxvdChsb2dBYnVuZGFuY2U9dG9wX2hpdHMkdGFibGUkbG9nQ1BNLCAKICAgICAgICAgICAgICBsb2dGQz10b3BfaGl0cyR0YWJsZSRsb2dGQywKICAgICAgICAgICAgICBkZS50YWdzPXdoaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpLAogICAgICAgICAgICAgIGxvd2Vzcz1UUlVFLAogICAgICAgICAgICAgIHhsYWI9ImxvZyhjb3VudHMgcGVyIG1pbGxpb24pIiwKICAgICAgICAgICAgICB5bGFiPSJsb2coZm9sZC1jaGFuZ2UpIiwKICAgICAgICAgICAgICBtYWluPSJGaWd1cmUgNDogTUEgUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IAogICAgICAgICAgICAgIGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIGFjcm9zcyAKICAgICAgICAgICAgICBjbGluaWNhbCBzdWJ0eXBlcywgYWdncmVnYXRlIGRlc2lnbiIpCmxlZ2VuZCgidG9wcmlnaHQiLCB0aXRsZT0iU2lnbmlmaWNhbmNlIiwKICAgICAgIGxlZ2VuZD1jKCJub3Qgc2lnbmlmaWNhbnQiLCAKICAgICAgICAgICAgICAgICJzaWduaWZpY2FudCBhZnRlciBjb3JyZWN0aW9uIiksIAogICAgICAgY29sPWMoImJsYWNrIiwgInJlZCIpLCBwY2g9MSwgY2V4PTAuOCkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcuY2FwPSJGaWd1cmUgNTogTUEgUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIGFzc29jaWF0ZWQgd2l0aCBFUiBleHByZXNzaW9uIn0KZWRnZVI6Om1hUGxvdChsb2dBYnVuZGFuY2U9dG9wX2VycCR0YWJsZSRsb2dDUE0sIAogICAgICAgICAgICAgIGxvZ0ZDPXRvcF9lcnAkdGFibGUkbG9nRkMsCiAgICAgICAgICAgICAgZGUudGFncz13aGljaCh0b3BfZXJwJHRhYmxlJEZEUiA8IDAuMDUpLAogICAgICAgICAgICAgIGxvd2Vzcz1UUlVFLAogICAgICAgICAgICAgIHhsYWI9ImxvZyhjb3VudHMgcGVyIG1pbGxpb24pIiwKICAgICAgICAgICAgICB5bGFiPSJsb2coZm9sZC1jaGFuZ2UpIiwKICAgICAgICAgICAgICBtYWluPSJGaWd1cmUgNTogTUEgUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IAogICAgICAgICAgICAgIGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIAogICAgICAgICAgICAgIGFzc29jaWF0ZWQgd2l0aCBFUiBleHByZXNzaW9uIikKbGVnZW5kKCJ0b3ByaWdodCIsIHRpdGxlPSJTaWduaWZpY2FuY2UiLAogICAgICAgbGVnZW5kPWMoIm5vdCBzaWduaWZpY2FudCIsIAogICAgICAgICAgICAgICAgInNpZ25pZmljYW50IGFmdGVyIGNvcnJlY3Rpb24iKSwgCiAgICAgICBjb2w9YygiYmxhY2siLCAicmVkIiksIHBjaD0xLCBjZXg9MC44KQpgYGAKCiMjIyBWb2xjYW5vIFBsb3QKClRoZSB2b2xjYW5vIHBsb3QgcHJvdmlkZXMgYW5vdGhlciB2aXN1YWwgZm9yIHRoZSBzcHJlYWQgb2Ygb3VyIGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhbmQgdGhlaXIgc2lnbmlmaWNhbmNlLCBib3RoIGJlZm9yZSBhbmQgYWZ0ZXIgY29ycmVjdGlvbi4KClRoZSBncmVlbiBwb2ludHMgYXJlIHRob3NlIHdpdGggc2lnbmlmaWNhbnQgcC12YWx1ZXMgYmVmb3JlIGNvcnJlY3Rpb24sIHdpdGggdGhlIHJlZCBwb2ludHMgYmVpbmcgc2lnbmlmaWNhbnQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbi4KCmBgYHtyLCBmaWcuaGVpZ2h0PTYsIGZpZy5jYXA9IkZpZ3VyZSA2OiBWb2xjYW5vIFBsb3Qgb2Ygc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbiBhY3Jvc3MgY2xpbmljYWwgc3VidHlwZXMsIGFnZ3JlZ2F0ZSBkZXNpZ24ifQpwbG90KHRvcF9oaXRzJHRhYmxlJGxvZ0ZDLCAtMTAqbG9nMTAodG9wX2hpdHMkdGFibGUkUFZhbHVlKSwKICAgICBtYWluPSJGaWd1cmUgNjogVm9sY2FubyBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgCiAgICAgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gCiAgICAgYWNyb3NzIGNsaW5pY2FsIHN1YnR5cGVzLCBhZ2dyZWdhdGUgZGVzaWduIiwKICAgICB4bGFiPSJsb2coZm9sZCBjaGFuZ2UpIiwKICAgICB5bGFiPSItMTBebG9nKHAtdmFsdWUpIikKIyBoaWdobGlnaHQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCnBvaW50cyh0b3BfaGl0cyR0YWJsZSRsb2dGQ1t3aGljaCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KV0sCiAgICAgICAtMTAqbG9nMTAodG9wX2hpdHMkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUgPCAwLjA1KV0sCiAgICAgICBjb2w9ImdyZWVuIikKcG9pbnRzKHRvcF9oaXRzJHRhYmxlJGxvZ0ZDW3doaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfaGl0cyR0YWJsZSRQVmFsdWUpW3doaWNoKHRvcF9oaXRzJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIGNvbD0icmVkIikKbGVnZW5kKCJ0b3BsZWZ0IiwgdGl0bGU9IlNpZ25pZmljYW5jZSIsCiAgICAgICBsZWdlbmQ9Yygibm90IHNpZ25pZmljYW50IiwgCiAgICAgICAgICAgICAgICAic2lnbmlmaWNhbnQgYmVmb3JlIGNvcnJlY3Rpb24iLCAKICAgICAgICAgICAgICAgICJzaWduaWZpY2FudCBhZnRlciBjb3JyZWN0aW9uIiksIAogICAgICAgY29sPWMoImJsYWNrIiwgImdyZWVuIiwgInJlZCIpLCBwY2g9MSwgY2V4PTAuOCkKYGBgCgpgYGB7ciwgZmlnLmhlaWdodD02LCBmaWcuY2FwPSJGaWd1cmUgNzogVm9sY2FubyBQbG90IG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGFmdGVyIGNvcnJlY3Rpb24gYXNzb2NpYXRlZCB3aXRoIEVSIGV4cHJlc3Npb24ifQpwbG90KHRvcF9lcnAkdGFibGUkbG9nRkMsIC0xMCpsb2cxMCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSksCiAgICAgbWFpbj0iRmlndXJlIDc6IFZvbGNhbm8gUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IAogICAgIGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIAogICAgIGFzc29jaWF0ZWQgd2l0aCBFUiBleHByZXNzaW9uIiwKICAgICB4bGFiPSJsb2coZm9sZCBjaGFuZ2UpIiwKICAgICB5bGFiPSItMTBebG9nKHAtdmFsdWUpIikKIyBoaWdobGlnaHQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCnBvaW50cyh0b3BfZXJwJHRhYmxlJGxvZ0ZDW3doaWNoKHRvcF9lcnAkdGFibGUkUFZhbHVlIDwgMC4wNSldLAogICAgICAgLTEwKmxvZzEwKHRvcF9lcnAkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpXSwKICAgICAgIGNvbD0iZ3JlZW4iKQpwb2ludHModG9wX2VycCR0YWJsZSRsb2dGQ1t3aGljaCh0b3BfZXJwJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfZXJwJHRhYmxlJFBWYWx1ZSlbd2hpY2godG9wX2VycCR0YWJsZSRGRFIgPCAwLjA1KV0sCiAgICAgICBjb2w9InJlZCIpCmxlZ2VuZCgidG9wbGVmdCIsIHRpdGxlPSJTaWduaWZpY2FuY2UiLAogICAgICAgbGVnZW5kPWMoIm5vdCBzaWduaWZpY2FudCIsIAogICAgICAgICAgICAgICAgInNpZ25pZmljYW50IGJlZm9yZSBjb3JyZWN0aW9uIiwgCiAgICAgICAgICAgICAgICAic2lnbmlmaWNhbnQgYWZ0ZXIgY29ycmVjdGlvbiIpLCAKICAgICAgIGNvbD1jKCJibGFjayIsICJncmVlbiIsICJyZWQiKSwgcGNoPTEsIGNleD0wLjgpCmBgYAoKVGhpcyB2b2xjYW5vIHBsb3Qgb2YgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIHdpdGggcmVnYXJkcyB0byBgRVItYCBhbmQgYEVSK2AgaXMgdmVyeSBpbnRlcmVzdGluZyBnaXZlbiBpdHMgc3Ryb25nIHNrZXcgdG93YXJkcyB1cC1yZWd1bGF0aW9uLgoKYGBge3IsIGZpZy5oZWlnaHQ9NiwgZmlnLmNhcD0iRmlndXJlIDg6IFZvbGNhbm8gUGxvdCBvZiBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIGFzc29jaWF0ZWQgd2l0aCBIRVIyIGV4cHJlc3Npb24ifQpwbG90KHRvcF9oZXIycCR0YWJsZSRsb2dGQywgLTEwKmxvZzEwKHRvcF9oZXIycCR0YWJsZSRQVmFsdWUpLAogICAgIG1haW49IkZpZ3VyZSA4OiBWb2xjYW5vIFBsb3Qgb2Ygc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSAKICAgICBleHByZXNzZWQgZ2VuZXMgYWZ0ZXIgY29ycmVjdGlvbiAKICAgICBhc3NvY2lhdGVkIHdpdGggSEVSMiBleHByZXNzaW9uIiwKICAgICB4bGFiPSJsb2coZm9sZCBjaGFuZ2UpIiwKICAgICB5bGFiPSItMTBebG9nKHAtdmFsdWUpIikKIyBoaWdobGlnaHQgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzCnBvaW50cyh0b3BfaGVyMnAkdGFibGUkbG9nRkNbd2hpY2godG9wX2hlcjJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlIDwgMC4wNSldLAogICAgICAgY29sPSJncmVlbiIpCnBvaW50cyh0b3BfaGVyMnAkdGFibGUkbG9nRkNbd2hpY2godG9wX2hlcjJwJHRhYmxlJEZEUiA8IDAuMDUpXSwKICAgICAgIC0xMCpsb2cxMCh0b3BfaGVyMnAkdGFibGUkUFZhbHVlKVt3aGljaCh0b3BfaGVyMnAkdGFibGUkRkRSIDwgMC4wNSldLAogICAgICAgY29sPSJyZWQiKQpsZWdlbmQoInRvcGxlZnQiLCB0aXRsZT0iU2lnbmlmaWNhbmNlIiwKICAgICAgIGxlZ2VuZD1jKCJub3Qgc2lnbmlmaWNhbnQiLCAKICAgICAgICAgICAgICAgICJzaWduaWZpY2FudCBiZWZvcmUgY29ycmVjdGlvbiIsIAogICAgICAgICAgICAgICAgInNpZ25pZmljYW50IGFmdGVyIGNvcnJlY3Rpb24iKSwgCiAgICAgICBjb2w9YygiYmxhY2siLCAiZ3JlZW4iLCAicmVkIiksIHBjaD0xLCBjZXg9MC44KQpgYGAKCkJvdGggdGhlIGFnZ3JlZ2F0ZSBtb2RlbCBkZXNpZ24sIGFuZCB0aGUgYEhFUjJgIGRlc2lnbiBhcmUgZmFpcmx5IGV2ZW5seSBkaXN0cmlidXRlZCBhcm91bmQgMC4KCiMjIFZpc3VhbGl6aW5nIHRvcCBoaXRzCgojIyMgSGVhdG1hcAoKQWdncmVnYXRpbmcgb3VyIHRvcCBoaXRzIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcyBpbnRvIGEgaGVhdG1hcCwgd2UgY2FuIHNlZSB0aGUgZXhwcmVzc2lvbiB2aXN1YWxseSBhcyBzaG93biwgYWxvbmcgd2l0aCBhIGhlYXRtYXAgYW5ub3RhdGlvbiBjb3JyZXNwb25kaW5nIHRvIGVhY2ggYmluYXJ5IHBhaXJpbmcgcmVwcmVzZW50ZWQgYnkgdGhlIHN1YnR5cGUgY2xhc3NpZmllci4KCmBgYHtyfQp0b3BzIDwtIHJvd25hbWVzKHFsZi5zdWJ0eXBlcyR0YWJsZSlbCiAgcWxmLnN1YnR5cGVzJHRhYmxlJFBWYWx1ZSA8IDAuMDUKXQp0b3BfaGl0c19tYXRyaXggPSB0KHNjYWxlKAogIHQobm9ybV9tYXRyaXhbd2hpY2gocm93bmFtZXMobm9ybV9tYXRyaXgpICVpbiUgdG9wcyksXSkKKSkKCiMgY29sb3VycwppZiAobWluKHRvcF9oaXRzX21hdHJpeCkgPT0gMCkgewogIGhlYXRtYXBfY29sID0gY29sb3JSYW1wMihjKDAsIG1heCh0b3BfaGl0c19tYXRyaXgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYygid2hpdGUiLCAicmVkIikpCn0gZWxzZSB7CiAgaGVhdG1hcF9jb2wgPSBjb2xvclJhbXAyKGMobWluKHRvcF9oaXRzX21hdHJpeCksIDAsIG1heCh0b3BfaGl0c19tYXRyaXgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYygiYmx1ZSIsICJ3aGl0ZSIsICJyZWQiKSkKfQoKIyBhbm5vdGF0aW9ucwpoZXIyX2NvbCA8LSBjKCJsaWdodGdyZWVuIiwgInJlZCIpCm5hbWVzKGhlcjJfY29sKSA8LSBjKCdUUlVFJywgJ0ZBTFNFJykKZXJfY29sIDwtIGMoImRhcmtncmVlbiIsICJwaW5rIikKbmFtZXMoZXJfY29sKSA8LSBjKCdUUlVFJywgJ0ZBTFNFJykKCnR5cGVzX2RmJGhlcjIgPC0gZmFjdG9yKHR5cGVzX2RmJGhlcjIsIGxldmVscyA9IGMoJ1RSVUUnLCdGQUxTRScpKQp0eXBlc19kZiRlciA8LSBmYWN0b3IodHlwZXNfZGYkZXIsIGxldmVscyA9IGMoJ1RSVUUnLCdGQUxTRScpKQoKaGVhdG1hcF9hbm5vdGF0aW9uIDwtIENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwQW5ub3RhdGlvbigKICBkZiA9IGRhdGEuZnJhbWUoaGVyMiA9IHR5cGVzX2RmJGhlcjIsCiAgICAgICAgICAgICAgICAgIGVyID0gdHlwZXNfZGYkZXIpLAogIGNvbCA9IGxpc3QoaGVyMiA9IGhlcjJfY29sLCBlciA9IGVyX2NvbCksCiAgc2hvd19sZWdlbmQ9VFJVRQopCgpoZWF0bWFwIDwtIENvbXBsZXhIZWF0bWFwOjpIZWF0bWFwKGFzLm1hdHJpeCh0b3BfaGl0c19tYXRyaXgpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfcm93cz1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsdXN0ZXJfY29sdW1ucz1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93X2RlbmQ9VFJVRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19jb2x1bW5fZGVuZD1UUlVFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbD1oZWF0bWFwX2NvbCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19jb2x1bW5fbmFtZXM9RkFMU0UsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2hvd19yb3dfbmFtZXM9RkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfaGVhdG1hcF9sZWdlbmQ9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBuYW1lPSJjb2xvdXIgc2NhbGUiLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRvcF9hbm5vdGF0aW9uPWhlYXRtYXBfYW5ub3RhdGlvbiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2x1bW5fdGl0bGU9IkZpZ3VyZSA5OiBIZWF0bWFwIG9mIHRvcCBoaXRzIGFjcm9zcyAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbGluaWNhbCBzdWJ0eXBlcywgYWdncmVnYXRlIGRlc2lnbiIpCmBgYAoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9OCwgZmlnLmNhcD0iRmlndXJlIDk6IEhlYXQgbWFwIG9mIHRvcCBoaXRzIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcywgYWdncmVnYXRlIGRlc2lnbiB3aXRoIGJpbmFyeSBsYWJlbGxpbmcifQpoZWF0bWFwCmBgYAoKU3BlY2lmaWNhbGx5IGZvciBgRVJgIG92ZXJleHByZXNzaW9uIG9yIGxhY2sgdGhlcmVvZiwgSSBhZGRlZCBhbiBhZGRpdGlvbmFsIGhlYXRtYXAuCgpgYGB7cn0KdG9wc19lciA8LSByb3duYW1lcyhxbGYuZXJwJHRhYmxlKVsKICBxbGYuZXJwJHRhYmxlJFBWYWx1ZSA8IDAuMDUKXQp0b3BzX2VyX21hdHJpeCA9IHQoc2NhbGUoCiAgdChub3JtX21hdHJpeFt3aGljaChyb3duYW1lcyhub3JtX21hdHJpeCkgJWluJSB0b3BzX2VyKSxdKQopKQoKIyBjb2xvdXJzCmlmIChtaW4odG9wc19lcl9tYXRyaXgpID09IDApIHsKICBoZWF0bWFwX2NvbCA9IGNvbG9yUmFtcDIoYygwLCBtYXgodG9wc19lcl9tYXRyaXgpKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgYygid2hpdGUiLCAicmVkIikpCn0gZWxzZSB7CiAgaGVhdG1hcF9jb2wgPSBjb2xvclJhbXAyKGMobWluKHRvcHNfZXJfbWF0cml4KSwgMCwgbWF4KHRvcHNfZXJfbWF0cml4KSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgIGMoImJsdWUiLCAid2hpdGUiLCAicmVkIikpCn0KCmhlYXRtYXBfZXIgPC0gQ29tcGxleEhlYXRtYXA6OkhlYXRtYXAoYXMubWF0cml4KHRvcHNfZXJfbWF0cml4KSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX3Jvd3M9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjbHVzdGVyX2NvbHVtbnM9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X3Jvd19kZW5kPVRSVUUsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX2RlbmQ9VFJVRSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjb2w9aGVhdG1hcF9jb2wsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfY29sdW1uX25hbWVzPUZBTFNFLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNob3dfcm93X25hbWVzPUZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzaG93X2hlYXRtYXBfbGVnZW5kPVRSVUUsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbmFtZT0iY29sb3VyIHNjYWxlIiwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0b3BfYW5ub3RhdGlvbj1oZWF0bWFwX2Fubm90YXRpb24sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgY29sdW1uX3RpdGxlPSJGaWd1cmUgMTA6IEhlYXRtYXAgb2YgdG9wIGhpdHMgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXNzb2NpYXRlZCB3aXRoIEVSIG92ZXJleHByZXNzaW9uIikKYGBgCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD04LCBmaWcuY2FwPSJGaWd1cmUgMTA6IEhlYXRtYXAgb2YgdG9wIGhpdHMgYXNzb2NpYXRlZCB3aXRoIEVSIG92ZXJleHByZXNzaW9uIn0KaGVhdG1hcF9lcgpgYGAKCiMjIyBEbyBjb25kaXRpb25zIGNsdXN0ZXIgdG9nZXRoZXI/IEV4cGxhaW4uCgpJbiBmaWd1cmUgOSwgdGhlcmUgaXMgdmVyeSB2aXNpYmx5IGEgY2x1c3RlciBkZW1vbnN0cmF0ZWQgYmV0d2VlbiBoZWF0IGludGVuc2l0eSBhbmQgYEVSYCBvdmVyZXhwcmVzc2lvbiBvciBsYWNrIHRoZXJlb2Ygd2l0aCB0aGUgZ2VuZXMgcHJpbWFyaWx5IGluIHRoZSB0b3AgaGFsZiBiZWluZyBnZW5lcmFsbHkgaGlnaGx5IGV4cHJlc3NlZCBpbiBsYWNrIG9mIGBFUmAsIGFuZCBsb3dseSBleHByZXNzZWQgaW4gb3ZlcmV4cHJlc3Npb24gb2YgYEVSYC4gU2ltaWxhcmx5LCB0aGUgbG93ZXIgaGFsZiBvZiBnZW5lcyBwcmltYXJpbHkgZm9sbG93IHRoZSBvcHBvc2l0ZSB0cmVuZDsgbG93ZXIgZXhwcmVzc2lvbiBvbiBgRVItYCBhbmQgaGlnaGVyIGV4cHJlc3Npb24gb24gYEVSK2AuCgpJbiBmaWd1cmUgMTAsIGl0IGlzIG1vcmUgZGlmZmljdWx0IHRvIHNlZSB0aGUgY2x1c3RlciBwYXR0ZXJucy4gU2FtcGxlIDEgaGFzIHZlcnkgaW50ZW5zZSBSTkEgZXhwcmVzc2lvbnMgaW4gdGhlIHRvcCBoYWxmIG9mIGdlbmVzLCBidXQgaXRzIG1hdGNoaW5nIGBIRVIyKy9FUi1gIHN1YnR5cGUgbGFja3MgdGhpcyBhdCBhbGwuIFRoaXMgaW1wbGllcyB0aGUgYXNzb2NpYXRpb24gZ29lcyBpbiBhIGJyb2FkZXIgc2NhbGUgdGhhbiBsYWNrIG9mIGBFUmAgZm9yIHRoZXNlIGdlbmVzLiBEZXNwaXRlIDExIGdlbmVzIGJlaW5nIGFzc29jaWF0ZWQgd2l0aCBvdmVyZXhwcmVzc2lvbiBvZiBgRVJgLCBpdCBkb2VzIG5vdCBhcHBlYXIgdG8gc2hvdyBhIHZpc2libGUgY2x1c3RlciBvbiB0aGUgaGVhdG1hcCBsaWtlIHRoZSBhZ2dyZWdhdGUgZGVzaWduIGluIGZpZ3VyZSA5IGRvZXMgcHJldHR5IHdlbGwuCgojIFRocmVzaG9sZGVkIE92ZXItUmVwcmVzZW50YXRpb24gQW5hbHlzaXMKCldpdGggb3VyIHNpZ25pZmljYW50bHkgdXAtcmVndWxhdGVkLCBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZS1zZXRzLCB3ZSB3aWxsIHJ1biBhIHRocmVzaG9sZGVkIGdlbmUtc2V0IGVucmljaG1lbnQgYW5hbHlzaXMuCgpXZSBoYXZlIGByIGxlbmd0aCh3aGljaChxbGYuc3VidHlwZXMkdGFibGUkUFZhbHVlIDwgMC4wNSAmIHFsZi5zdWJ0eXBlcyR0YWJsZSRsb2dGQyA+IDApKWAgdXAtcmVndWxhdGVkIGdlbmVzLCBhbmQgYHIgbGVuZ3RoKHdoaWNoKHFsZi5zdWJ0eXBlcyR0YWJsZSRQVmFsdWUgPCAwLjA1ICYgcWxmLnN1YnR5cGVzJHRhYmxlJGxvZ0ZDIDwgMCkpYCBkb3duLXJlZ3VsYXRlZCBnZW5lcyBmb3Igb3VyIGFnZ3JlZ2F0ZSBtb2RlbCBkZXNpZ24gYWNyb3NzIGFsbCBjbGluaWNhbCBzdWJ0eXBlcy4KCmBgYHtyfQojIGNyZWF0ZSBub24tdGhyZXNob2xkZWQgZ2VuZSBzZXRzCm50X2dlbmVzZXQgPC0gcWxmLnN1YnR5cGVzJHRhYmxlCm50X2dlbmVzZXRbLCJyYW5rIl0gPC0gLWxvZzEwKG50X2dlbmVzZXQkUFZhbHVlKSAqIHNpZ24obnRfZ2VuZXNldCRsb2dGQykKbnRfZ2VuZXNldCA8LSBudF9nZW5lc2V0W29yZGVyKG50X2dlbmVzZXQkcmFuayksXQpgYGAKCmBgYHtyfQojIGNyZWF0ZSB0aHJlc2hvbGRlZCB1cCBhbmQgZG93biBnZW5lIHNldHMKdXByZWcgPC0gcm93bmFtZXMobnRfZ2VuZXNldClbd2hpY2gobnRfZ2VuZXNldCRQVmFsdWUgPCAwLjA1CiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICYgbnRfZ2VuZXNldCRsb2dGQyA+IDApXQpkb3ducmVnIDwtIHJvd25hbWVzKG50X2dlbmVzZXQpW3doaWNoKG50X2dlbmVzZXQkUFZhbHVlIDwgMC4wNQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICYgbnRfZ2VuZXNldCRsb2dGQyA8IDApXQpgYGAKCmBgYHtyfQojIGZ1bmN0aW9uIGZvciByZXRyaWV2aW5nIGc6R09TdCBmcm9tIGc6UHJvZmlsZXIKZ29zdF9yZXMgPC0gZnVuY3Rpb24ocXVlcnkpIHsKICByZXMgPC0gZ29zdChxdWVyeSA9IHF1ZXJ5LAogICAgICAgICAgICAgICAgICAgICAgc2lnbmlmaWNhbnQ9RkFMU0UsICMgc2V0IG91ciBvd24gdGhyZXNob2xkCiAgICAgICAgICAgICAgICAgICAgICBvcmRlcmVkX3F1ZXJ5ID0gVFJVRSwgIyBvcmRlcmVkIGJ5IHJhbmsKICAgICAgICAgICAgICAgICAgICAgIGV4Y2x1ZGVfaWVhPVRSVUUsICMgZXhjbHVkZSBlbGVjdHJvbmljIEdPIGFubm90YXRpb25zCiAgICAgICAgICAgICAgICAgICAgICBjb3JyZWN0aW9uX21ldGhvZCA9ICJmZHIiLCAjIEJICiAgICAgICAgICAgICAgICAgICAgICBvcmdhbmlzbSA9ICJoc2FwaWVucyIsCiAgICAgICAgICAgICAgICAgICAgICBzb3VyY2UgPSBjKCJSRUFDIiwiV1AiLCJHTzpCUCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR086Q0MiLCAiR086TUYiLCAiS0VHRyIpKQogIHJldHVybihyZXMpCn0KYGBgCgpJIHF1ZXJ5IG91ciBnZW5lc2V0cyB1c2luZyBgZzpQcm9maWxlcmAncyBgZzpHT1N0YC4KCmBgYHtyfQojIHVwIGFuZCBkb3duIHJlZ3VsYXRlZCB0aHJlc2hvbGRlZCBnZW5lcwphbGwgPC0gZ29zdF9yZXModW5pcXVlKGModXByZWcsIGRvd25yZWcpKSkKIyBvbmx5IHVwIHJlZ3VsYXRlZCB0aHJlc2hvbGRlZCBnZW5lcwp1cCA8LSBnb3N0X3Jlcyh1cHJlZykKIyBvbmx5IGRvd24gcmVndWxhdGVkIHRocmVzaG9sZGVkIGdlbmVzCmRvd24gPC0gZ29zdF9yZXMoZG93bnJlZykKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KYWxsJHJlc3VsdFsxOjUsYygzLCA5LCAxMSldICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSA3OiBIZWFkIG9mIHRocmVzaG9sZGVkIHVwIGFuZCBkb3duIHJlZ3VsYXRlZCBnZW5lcyBmcm9tIGc6R09TdCIpICU+JQogIGthYmxlX3N0eWxpbmcKYGBgCgpgYGB7ciwgZWNobz1GQUxTRX0KdXAkcmVzdWx0WzE6NSxjKDMsIDksIDExKV0gJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDg6IEhlYWQgb2YgdGhyZXNob2xkZWQgdXAtcmVndWxhdGVkIGdlbmVzIGZyb20gZzpHT1N0IikgJT4lCiAga2FibGVfc3R5bGluZwpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQpkb3duJHJlc3VsdFsxOjUsYygzLCA5LCAxMSldICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSA5OiBIZWFkIG9mIHRocmVzaG9sZGVkIGRvd24tcmVndWxhdGVkIGdlbmVzIGZyb20gZzpHT1N0IikgJT4lCiAga2FibGVfc3R5bGluZwpgYGAKCiMjIFdoaWNoIG1ldGhvZCBkaWQgeW91IGNob29zZSBhbmQgd2h5PwoKSSBjaG9zZSB0byB1c2UgYGc6UHJvZmlsZXJgIHdpdGggUiBzaW5jZSBpdCB3YXMgd2VsbCBkb2N1bWVudGVkIGJ5IFJ1dGggSXNzZXJsaW4gW0ByaXNzZXJsaW5dIGFuZCBJIGhhZCBmYW1pbGlhcml0eSB3aXRoIGl0IHRocm91Z2ggbXkgam91cm5hbCBlbnRyeS4gCgpgZzpQcm9maWxlcmAgcHJvdmlkZXMgYW4gYE9SQWAgKG92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMpIG1ldGhvZCwgYW5kIHRoaXMgaXMgZXhhY3RseSB0aGUgbWV0aG9kIEkgd2FudCB0byBwZXJmb3JtIG9uIG15IHRocmVzaG9sZGVkIGRhdGEuCgojIyBXaGljaCBhbm5vdGF0aW9uIGRhdGEgZGlkIHlvdSB1c2UgYW5kIHdoeT8gCgpJIGNob3NlIHRoZSBmb2xsb3dpbmcgYW5ub3RhdGlvbiBzb3VyY2VzIHRvIGdldCB0aGUgbW9zdCBjb21wcmVoZW5zaXZlIHJlc3VsdHMgZm9yIG91ciBmdW5jdGlvbmFsIGVucmljaG1lbnQgYW5hbHlzaXMgcmVsYXRpdmUgdG8gYmlvbG9naWNhbCBwcm9jZXNzZXMgYW5kIGdlbmUgb250b2xvZ3k6CgoqIGBHTzpCUGAgOiBgR2VuZSBPbnRvbG9neTogQmlvbG9naWNhbCBQcm9jZXNzZXNgCiogYFJFQUNgIDogYFJlYWN0b21lYAoqIGBXUGAgOiBgV2lraVBhdGh3YXlzYAoqIGBHTzpDQ2AgOiBgR2VuZSBPbnRvbG9neTogQ2VsbHVsYXIgQ29tcG9uZW50c2AKKiBgR086TUZgIDogYEdlbmUgT250b2xvZ3k6IE1vbGVjdWxhciBGdW5jdGlvbmAKKiBgS0VHR2AgOiBgS3lvdG8gRW5jeWNsb3BlZGlhIG9mIEdlbmVzIGFuZCBHZW5vbWVzYAoKYEdPOkJQYCwgYFJFQUNgLCBhbmQgYFdQYCB3ZXJlIHJlY29tbWVuZGVkIGJ5IFByb2Zlc3NvciBJc3NlcmxpbiwgaG93ZXZlciBJIHJhbiB0aGUgT1JBIHVzaW5nIHRoZXNlIGFuZCBmb3VuZCBub3RoaW5nIGp1bXBlZCBvdXQgZnJvbSB0aGUgcmVzdWx0aW5nIHBsb3RzLiBBcyBzdWNoLCBJIHJldmlzaXRlZCB0byBleHBhbmQgdGhlIHNjb3BlIG9mIGFubm90YXRpb24gc291cmNlcyBpbiBob3BlcyBmb3IgYSBtb3JlIGluZm9ybWF0aXZlIHJlc3VsdC4KCiMjIyBXaGF0IHZlcnNpb24gb2YgdGhlIGFubm90YXRpb24gYXJlIHlvdSB1c2luZz8KCmBgYHtyLCBlY2hvPUZBTFNFfQp2ZXJzaW9uX2luZm8gPC0gZ3Byb2ZpbGVyMjo6Z2V0X3ZlcnNpb25faW5mbyhvcmdhbmlzbSA9ICJoc2FwaWVucyIpCmdvYnAgPC0gdmVyc2lvbl9pbmZvJHNvdXJjZXMkYEdPOkJQYApnb2NjIDwtIHZlcnNpb25faW5mbyRzb3VyY2VzJGBHTzpDQ2AKZ29tZiA8LSB2ZXJzaW9uX2luZm8kc291cmNlcyRgR086TUZgCmBgYAoKRm9yIGBnOlByb2ZpbGVyYCB2ZXJzaW9uIGluZm9ybWF0aW9uLCBJIHVzZWQ6CgoqIGBnOlByb2ZpbGVyYCB2ZXJzaW9uOiBfX2ByIHZlcnNpb25faW5mbyRncHJvZmlsZXJfdmVyc2lvbmBfXwoqIGBiaW9tYVJ0YCB2ZXJzaW9uOiBfX2ByIHZlcnNpb25faW5mbyRiaW9tYXJ0X3ZlcnNpb25gX18KCkZvciB0aGUgYW5ub3RhdGlvbiBzb3VyY2VzIHNlbGVjdGVkIGluIG15IHF1ZXJ5LCBJIHVzZWQ6CgoqIGBHTzpCUGAgdmVyc2lvbiBfX2ByIGdvYnAkdmVyc2lvbmBfXyAKKiBgUkVBQ2AgdmVyc2lvbiBfX2ByIHZlcnNpb25faW5mbyRzb3VyY2VzJFJFQUMkdmVyc2lvbmBfXwoqIGBXUGAgdmVyc2lvbiBfX2ByIHZlcnNpb25faW5mbyRzb3VyY2VzJFdQJHZlcnNpb25gX18KKiBgR086Q0NgIHZlcnNpb24gX19gciBnb2NjJHZlcnNpb25gX18gCiogYEdPOk1GYCB2ZXJzaW9uIF9fYHIgZ29tZiR2ZXJzaW9uYF9fIAoqIGBLRUdHYCB2ZXJzaW9uIF9fYHIgdmVyc2lvbl9pbmZvJHNvdXJjZXMkS0VHRyR2ZXJzaW9uYF9fCgojIyBIb3cgbWFueSBnZW5lLXNldHMgd2VyZSByZXR1cm5lZCB3aXRoIHdoYXQgdGhyZXNob2xkcz8KCmBgYHtyLCBlY2hvPUZBTFNFLCByZXN1bHRzPSdoaWRlJ30KdGhyZXNob2xkX3JlcyA8LSBmdW5jdGlvbihyZXN1bHQsIG1pbiwgbWF4LCBpbnRlcnNlY3Rpb24pIHsKICByZXQgPC0gc3Vic2V0KHJlc3VsdCwgdGVybV9zaXplID49IG1pbiAmCiAgICAgICAgICAgICAgICB0ZXJtX3NpemUgPD0gbWF4ICYKICAgICAgICAgICAgICAgIGludGVyc2VjdGlvbl9zaXplID49IGludGVyc2VjdGlvbiwKICAgICAgICAgICAgICAgIHNlbGVjdCA9IGModGVybV9pZCwgdGVybV9uYW1lLCBwX3ZhbHVlLCBzaWduaWZpY2FudCkpCiAgcmV0dXJuKHJldCkKfQpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQp0aHJlc2hvbGRfZGYgPC0gZGF0YS5mcmFtZSgKICBjKGRpbSh0aHJlc2hvbGRfcmVzKGFsbCRyZXN1bHQsIDMsIDEwMCwgNSkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAxMDAsIDUpKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKGRvd24kcmVzdWx0LCAzLCAxMDAsIDUpKVsxXSksCiAgYyhkaW0odGhyZXNob2xkX3JlcyhhbGwkcmVzdWx0LCAzLCAyNTAsIDUpKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKHVwJHJlc3VsdCwgMywgMjUwLCA1KSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMjUwLCA1KSlbMV0pLAogIGMoZGltKHRocmVzaG9sZF9yZXMoYWxsJHJlc3VsdCwgMywgMTAwMCwgNSkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAxMDAwLCA1KSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMTAwMCwgNSkpWzFdKSwKICBjKGRpbSh0aHJlc2hvbGRfcmVzKGFsbCRyZXN1bHQsIDMsIDEwMDAwLCA1KSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyh1cCRyZXN1bHQsIDMsIDEwMDAwLCA1KSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMTAwMDAsIDUpKVsxXSksCiAgcm93Lm5hbWVzPWMoIlVwICYgRG93biIsICJVcCIsICJEb3duIikpCgp0aHJlc2hvbGRfZGYgJT4lCiAga25pdHI6OmthYmxlKGNhcHRpb249IlRhYmxlIDEwOiBHZW5lLXNldCBzaXplcyBmb3IgZGlmZmVyZW50IG1heGltdW0gdGhyZXNob2xkcyB3aXRoIG1pbmltdW0gaW50ZXJzZWN0aW9uIG9mIDUiLAogICAgICAgICAgICAgICBjb2wubmFtZXM9YygiTWF4IDEwMCIsICJNYXggMjUwIiwgIk1heCAxMDAwIiwgIk1heCAxMDAwMDAiKSkgJT4lCiAga2FibGVfc3R5bGluZygpCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnRocmVzaG9sZF9kZiA8LSBkYXRhLmZyYW1lKAogIGMoZGltKHRocmVzaG9sZF9yZXMoYWxsJHJlc3VsdCwgMywgMTAwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAxMDAsIDEwKSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyhkb3duJHJlc3VsdCwgMywgMTAwLCAxMCkpWzFdKSwKICBjKGRpbSh0aHJlc2hvbGRfcmVzKGFsbCRyZXN1bHQsIDMsIDI1MCwgMTApKVsxXSwKICAgIGRpbSh0aHJlc2hvbGRfcmVzKHVwJHJlc3VsdCwgMywgMjUwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXMoZG93biRyZXN1bHQsIDMsIDI1MCwgMTApKVsxXSksCiAgYyhkaW0odGhyZXNob2xkX3JlcyhhbGwkcmVzdWx0LCAzLCAxMDAwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAxMDAwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXMoZG93biRyZXN1bHQsIDMsIDEwMDAsIDEwKSlbMV0pLAogIGMoZGltKHRocmVzaG9sZF9yZXMoYWxsJHJlc3VsdCwgMywgMTAwMDAsIDEwKSlbMV0sCiAgICBkaW0odGhyZXNob2xkX3Jlcyh1cCRyZXN1bHQsIDMsIDEwMDAwLCAxMCkpWzFdLAogICAgZGltKHRocmVzaG9sZF9yZXMoZG93biRyZXN1bHQsIDMsIDEwMDAwLCAxMCkpWzFdKSwKICByb3cubmFtZXM9YygiVXAgJiBEb3duIiwgIlVwIiwgIkRvd24iKSkKCnRocmVzaG9sZF9kZiAlPiUKICBrbml0cjo6a2FibGUoY2FwdGlvbj0iVGFibGUgMTE6IEdlbmUtc2V0IHNpemVzIGZvciBkaWZmZXJlbnQgbWF4aW11bSB0aHJlc2hvbGRzIHdpdGggbWluaW11bSBpbnRlcnNlY3Rpb24gb2YgMTAiLAogICAgICAgICAgICAgICBjb2wubmFtZXM9YygiTWF4IDEwMCIsICJNYXggMjUwIiwgIk1heCAxMDAwIiwgIk1heCAxMDAwMDAiKSkgJT4lCiAga2FibGVfc3R5bGluZygpCmBgYAoKQWZ0ZXIgdGhyZXNob2xkaW5nIHdpdGggbWF4aW11bSB2YWx1ZSBvZiAxMDAgYW5kIG1pbmltdW0gaW50ZXJzZWN0aW9uIG9mIDEwLCB3ZSBjYW4gc2VlIHRoZSB0ZXJtcyByZW1haW4gc2ltaWxhci4KCmBgYHtyLCBlY2hvPUZBTFNFfQp0aHJlc2hvbGRfcmVzKGFsbCRyZXN1bHQsIDMsIDEwMCwgMTApWzE6NSxdICU+JQogIGtuaXRyOjprYWJsZShjYXB0aW9uPSJUYWJsZSAxMjogSGVhZCBvZiB0aHJlc2hvbGRlZCBbMywgMTAwXSB1cCBhbmQgZG93bi1yZWd1bGF0ZWQgZ2VuZXMgZnJvbSBPUkEgd2l0aCBpbnRlcnNlY3Rpb24gMTAiKSAlPiUKICBrYWJsZV9zdHlsaW5nCmBgYAoKYGBge3IsIGVjaG89RkFMU0V9CnRocmVzaG9sZF9yZXModXAkcmVzdWx0LCAzLCAxMDAsIDEwKVsxOjUsXSAlPiUKICBrbml0cjo6a2FibGUoY2FwdGlvbj0iVGFibGUgMTM6IEhlYWQgb2YgdGhyZXNob2xkZWQgWzMsIDEwMF0gdXAtcmVndWxhdGVkIGdlbmVzIGZyb20gT1JBIHdpdGggaW50ZXJzZWN0aW9uIDEwIikgJT4lCiAga2FibGVfc3R5bGluZwpgYGAKCmBgYHtyLCBlY2hvPUZBTFNFfQp0aHJlc2hvbGRfcmVzKGRvd24kcmVzdWx0LCAzLCAxMDAsIDEwKVsxOjUsXSAlPiUKICBrbml0cjo6a2FibGUoY2FwdGlvbj0iVGFibGUgMTQ6IEhlYWQgb2YgdGhyZXNob2xkZWQgWzMsIDEwMF0gZG93bi1yZWd1bGF0ZWQgZ2VuZXMgZnJvbSBPUkEgd2l0aCBpbnRlcnNlY3Rpb24gMTAiKSAlPiUKICBrYWJsZV9zdHlsaW5nCmBgYAoKQXMgc3VjaCwgd2UgZmluZCB0aGF0IHVwLXJlZ3VsYXRlZCBnZW5lcyBoYXZlIHNvbWUgc2lnbmlmaWNhbnQgZ2VuZS1zZXRzIGFmdGVyIHRocmVzaG9sZGluZywgd2hlcmVhcyBvdXIgZG93bi1yZWd1bGF0ZWQgZ2VuZXMgZmFpbCB0byBtYWludGFpbiBzaWduaWZpY2FuY2UuCgpPdXIgY29tYmluYXRpb24gdGFibGUgc2hvd3MgdXMgc3Ryb25nIG92ZXJsYXAgd2l0aCB0aGUgdXAtcmVndWxhdGVkIGdlbmVzLCBmdXJ0aGVyIHN1cHBvcnRpbmcgdGhlIHNpZ25pZmljYW5jZSBvZiBvdXIgdXAtcmVndWxhdGlvbiBza2V3ZWQgcmVzdWx0cy4KCiMjIENvbXBhcmluZyB1cC1yZWd1bGF0ZWQgYW5kIGRvd24tcmVndWxhdGVkIHNlcGFyYXRlIHZzLiB0b2dldGhlcgoKVGhlIGZvbGxvd2luZyBmaWd1cmVzIGRlbW9uc3RyYXRlIHRoZSBvdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIHBsb3RzIGZvciBib3RoIHVwICYgZG93biByZWd1bGF0ZWQsIHVwLXJlZ3VsYXRlZCwgYW5kIGRvd24tcmVndWxhdGVkIGdlbmVzIHJlc3BlY3RpdmVseSB3aXRoIG9ubHkgYSBjb3VwbGUgb2YgcG9pbnRzIG1hbnVhbGx5IGhpZ2hsaWdodGVkLgoKIVtGaWd1cmUgMTE6IE92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMgb2YgVXAgYW5kIERvd24gcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzXSgvaG9tZS9yc3R1ZGlvL3Byb2plY3RzL2ZpZ3VyZXMvYWxsX29yYS5wbmcpCgpgYGB7ciwgZWNobz1GQUxTRSwgZmlnLmhlaWdodD03LCBmaWcuY2FwPSJGaWd1cmUgMTE6IE92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMgb2YgVXAgYW5kIERvd24tcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIn0KIyBhbGxfcGxvdCA8LSBnb3N0cGxvdChhbGwsIGNhcHBlZCA9IEZBTFNFLCBpbnRlcmFjdGl2ZSA9IEZBTFNFKQojIGFsbF9wdWIgPC0gcHVibGlzaF9nb3N0cGxvdChhbGxfcGxvdCwKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlnaGxpZ2h0X3Rlcm1zID0gYygiR086MDA0NTI5NiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdPOjAwMzE5ODEiLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiR086MDE0MDUxMyIpICkgKwojICAgZ2d0aXRsZSgiRmlndXJlIDExOiBPdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIG9mIFVwIGFuZCBEb3duLXJlZ3VsYXRlZCBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpCmBgYAo8YnIvPgoKIVtGaWd1cmUgMTI6IE92ZXItcmVwcmVzZW50YXRpb24gYW5hbHlzaXMgb2YgVXAtcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzXSgvaG9tZS9yc3R1ZGlvL3Byb2plY3RzL2ZpZ3VyZXMvdXBfb3JhLnBuZykKCmBgYHtyLCBlY2hvPUZBTFNFLCBmaWcuaGVpZ2h0PTcsIGZpZy5jYXA9IkZpZ3VyZSAxMjogT3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyBvZiBVcC1yZWd1bGF0ZWQgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMifQojIHVwX3Bsb3QgPC0gZ29zdHBsb3QodXAsIGNhcHBlZCA9IEZBTFNFLCBpbnRlcmFjdGl2ZSA9IEZBTFNFKQojIHVwX3B1YiA8LSBwdWJsaXNoX2dvc3RwbG90KHVwX3Bsb3QsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgIGhpZ2hsaWdodF90ZXJtcyA9IGMoIkdPOjAwNDUyOTYiLAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIkdPOjAwMzE5ODEiLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTzowMTQwNTEzIikpICsKIyAgIGdndGl0bGUoIkZpZ3VyZSAxMjogT3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyBvZiBVcC1yZWd1bGF0ZWQgc2lnbmlmaWNhbnRseSBkaWZmZXJlbnRpYWxseSBleHByZXNzZWQgZ2VuZXMiKQpgYGAKPGJyLz4KCiFbRmlndXJlIDEzOiBPdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIG9mIERvd24tcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzXSgvaG9tZS9yc3R1ZGlvL3Byb2plY3RzL2ZpZ3VyZXMvZG93bl9vcmEucG5nKQoKYGBge3IsIGVjaG89RkFMU0UsIGZpZy5oZWlnaHQ9NywgZmlnLmNhcD0iRmlndXJlIDEzOiBPdmVyLXJlcHJlc2VudGF0aW9uIGFuYWx5c2lzIG9mIERvd24tcmVndWxhdGVkIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIn0KIyBkb3duX3Bsb3QgPC0gZ29zdHBsb3QoZG93biwgY2FwcGVkID0gRkFMU0UsIGludGVyYWN0aXZlID0gRkFMU0UpCiMgZG93bl9wdWIgPC0gcHVibGlzaF9nb3N0cGxvdChkb3duX3Bsb3QsIAojICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaGlnaGxpZ2h0X3Rlcm1zID0gYygiR086MDA0NTI5NiIsCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTzowMDMxOTgxIiwgCiMgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJHTzowMTQwNTEzIikpICsKIyAgIGdndGl0bGUoIkZpZ3VyZSAxMjogT3Zlci1yZXByZXNlbnRhdGlvbiBhbmFseXNpcyBvZiBEb3duLXJlZ3VsYXRlZCBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyIpCmBgYAoKIyMjIEhvdyBkbyB0aGVzZSByZXN1bHRzIGNvbXBhcmU/CgpTaW5jZSB0aGUgdXAtcmVndWxhdGVkIGdlbmUgcmVzdWx0cyB0ZW5kIHRvIGV4Y2VlZCB0aGUgZG93bi1yZWd1bGF0ZWQgZ2VuZSByZXN1bHRzIGluIHRlcm1zIG9mIHRlcm0gc2lnbmlmaWNhbmNlLCB0aGUgY29tYmluZWQgcGxvdCBhcHBlYXJzIHRvIG1vcmUgY2xvc2VseSByZXNlbWJsZSB0aGUgdXAtcmVndWxhdGVkIHBsb3QuCgpJbiBvdXIgY2FzZSwgT1JBIG9mIHVwIGFuZCBkb3duLXJlZ3VsYXRlZCBnZW5lcyBpbiBjb21iaW5hdGlvbiBkaWQgbm90IGhhdmUgYSBsYXJnZSBlZmZlY3Qgb24gdGhlIHJlc3VsdHMsIGJ1dCB0aGlzIGlzIGJlY2F1c2UgdGhlIHVwLXJlZ3VsYXRlZCBnZW5lcyBvdmVyc2hhZG93IHRoZSBkb3duLXJlZ3VsYXRlZC4gSWYgdGhpcyB3ZXJlIGEgZGlmZmVyZW50IGNhc2UsIHdlIGNvdWxkIHNlZSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSB1cC0gYW5kIGRvd24tcmVndWxhdGVkIHBsb3RzIG92ZXJzaGFkb3dlZCBhbmQgbWVsdGVkIGJ5IHRoZSBjb21iaW5hdGlvbiBwbG90LiBBcyBzdWNoLCBpdCBpcyBpbXBvcnRhbnQgdG8gbG9vayBhdCBib3RoIHVwLSBhbmQgZG93bi1yZWd1bGF0ZWQgc2VwYXJhdGVseS4KCkFsdGhvdWdoLCBpbiB0ZXJtcyBvZiBvdXIgcmVzdWx0cyBvZiB0aGlzIGFuYWx5c2lzLCBhbHRob3VnaCBzb21lIHRlcm1zIGFyZSBzaWduaWZpY2FudCBhY2NvcmRpbmcgdG8gb3VyIGFyYml0cmFyeSB0aHJlc2hvbGQsIG5vbmUgb2YgdGhlbSBhcmUgc3RyaWtpbmdseSBzbyB3aXRoIG1heGltdW0gLWxvZyhhZGp1c3RlZCBwLXZhbHVlcykgb25seSByZWFjaGluZyB1cCB0byBhYm91dCAzIG1heGltdW0sIHdoZXJlYXMgcGxvdHMgc2VlbiB3aXRoIHN0cm9uZ2VyIGZ1bmN0aW9uYWwgZW5yaWNobWVudCBwcmVzZW5jZSByZWFjaCB1cCBtdWNoIGhpZ2hlciB0b3dhcmRzIDEwLTE2Ky4KCiMgSW50ZXJwcmV0YXRpb24KCiMjIERvIHRoZSBvdmVyLXJlcHJlc2VudGF0aW9uIHJlc3VsdHMgc3VwcG9ydCBjb25jbHVzaW9ucyBvciBtZWNoYW5pc21zIGRpc2N1c3NlZCBpbiB0aGUgb3JpZ2luYWwgcGFwZXI/CgpUaGUgb3JpZ2luYWwgcGFwZXIgaW5jbHVkZXMgc3Vic3RhbnRpYWxseSBtb3JlIHByb2Nlc3Npbmcgb2YgdGhpcyBkYXRhIGluIGFkZGl0aW9uIHRvIHRoZSBzaW5nbGUtY2VsbCBSTkEgc2VxdWVuY2luZyBkYXRhIHRoZXkgYWNxdWlyZWQgaW4gdGFuZGVtLCBzbyBpdCBpcyBkaWZmaWN1bHQgdG8gc2F5IHdoZXRoZXIgdGhpcyBzdXBwb3J0cyB0aG9zZSByZXN1bHRzLiBOb25lIG9mIG15IHNpZ25pZmljYW50IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhcHBlYXIgdGhyb3VnaG91dCB0aGUgcmVwb3J0IHdoYXRzb2V2ZXIuIFRoZSBkaXNjdXNzaW9uIGFuZCByZXN1bHRzIHNlY3Rpb24gZm9yIHRoZSBidWxrIFJOQS1zZXF1ZW5jaW5nIGlzIHZlcnkgbGFja2x1c3RlciBjb21wYXJlZCB0byB0aGUgcmVzdCBvZiB0aGUgYW5hbHlzaXMgYW5kIHJlc3VsdHMgZm91bmQgYnkgc3BhdGlhbCByZXNvbHV0aW9uIG9mIHNpbmdsZS1jZWxsIFJOQSBzZXF1ZW5jaW5nLiBUaGUgUk5BIHNlcXVlbmNpbmcgaGVhdG1hcCBhcHBlYXJzIHNpbWlsYXIgdG8gbWluZSwgYWx0aG91Z2ggdGhleSB1c2VkIHNjYWxlZCBtZWFuIGludGVyYWN0aW9uIHNjb3JlIGFuZCBzdWJ0eXBlZCBvbmx5IGZvciBgRVJgIGFuZCBgVE5CQ2AgYXMgb3Bwb3NlZCB0byB0aGUgZm91ciBhdmFpbGFibGUgY2xpbmljYWwgc3VidHlwZXMuIEkgY2FuIHVuZGVyc3RhbmQgdGhpcyBhcHByb2FjaCBzaW5jZSB0aGUgYEhFUjJgIHN1YnR5cGUgcHJlc2VuY2Ugd2FzIHJlbGF0aXZlbHkgc21hbGwgY29tcGFyZWQgdG8gdGhlIHJlc3Qgb2YgdGhlIHNhbXBsZXMuCgpUaGVyZSBpcyBub3QgbXVjaCBmdW5jdGlvbmFsIGVucmljaG1lbnQgYXBwYXJlbnRseSBkaXN0aW5ndWlzaGluZyB0aGUgY2xhc3NpZmllZCBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIGluIHRoaXMgZGF0YXNldDsgYWx0aG91Z2ggaWYgd2UgaGFkIHRvIGxvb2sgYXQgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgdGVybShzKSwgb3VyIGFuYWx5c2lzIHdvdWxkIGRyYXcgb3VyIGF0dGVudGlvbiB0byBjYWRoZXJpbiBiaW5kaW5nLCBpZS4gW0dPOjAwNDUyOTZdKGh0dHBzOi8vYW1pZ28uZ2VuZW9udG9sb2d5Lm9yZy9hbWlnby90ZXJtL0dPOjAwNDUyOTYpLCBvZiB3aGljaCBpcyBub3QgcHJlc2VudCBpbiB0aGUgcGFwZXIncyBjb25jbHVzaW9ucy4gQXMgc3VjaCwgbXkgZmluZGluZ3MgZG8gbm90IHN1cHBvcnQgdGhlIG1lY2hhbmlzbXMgb3IgY29uY2x1c2lvbnMgZGlzY3Vzc2VkIGluIHRoZSBvcmlnaW5hbCBwYXBlciwgYWx0aG91Z2ggdGhhdCBkb2VzIG5vdCBkZW55IG15IGZpbmRpbmdzLgoKIyMgQ2FuIHlvdSBmaW5kIGV2aWRlbmNlLCBpZS4gcHVibGljYXRpb25zLCB0byBzdXBwb3J0IHNvbWUgb2YgdGhlIHJlc3VsdHMgdGhhdCB5b3Ugc2VlPyBIb3cgZG9lcyB0aGlzIGV2aWRlbmNlIHN1cHBvcnQgeW91ciByZXN1bHRzPwoKQ29udGludWluZyB3aXRoIHRoZSBtb3N0IHNpZ25pZmljYW50IEdPIHRlcm0gZnJvbSBvdXIgYW5hbHlzaXMtLWNhZGhlcmluIGJpbmRpbmctLXRoZXJlIGlzIHN1YnN0YW50aWFsIGV2aWRlbmNlIHRoYXQgY2FkaGVyaW5zIGFyZSBpbnRlZ3JhbCB0byBtYW1tYXJ5IGdsYW5kIGZ1bmN0aW9uLCBhbmQgbWlzZXhwcmVzc2lvbiBvZiBzdWNoIGxlYWRzIHRvIGluY3JlYXNlZCBtb3RpbGl0eSBhbmQgY29uc2VxdWVudGx5IGdyZWF0ZXIgbGlrZWxpaG9vZCBvZiBtZXRhc3Rhc2VzIGZvcm1hdGlvbiBbQGRlcnlja2UyMDA0bl0uIEUtY2FkaGVyaW4gaXMgb25lIG9mIHRoZSBtb3N0IHdpZGVseSBleHByZXNzZWQgdHVtb3VyIHN1cHByZXNzb3JzIGluIGJyZWFzdCBjYW5jZXIsIGhvd2V2ZXIgY2FkaGVyaW4tYmluZGluZyBvbiBpdHMgb3duIGlzIHJhdGhlciB2YWd1ZSBhbmQgZGlmZmljdWx0IHRvIGRyYXcgY29uY2x1c2lvbnMgZnJvbS4gV2UgY2FuIGNvbmNsdWRlLCBob3dldmVyLCB0aGF0IGNhZGhlcmlucyBhcmUgYXNzb2NpYXRlZCB3aXRoIGJyZWFzdCBjYW5jZXIgaW4gbXVsdGlwbGUgd2F5cywgYW5kIHNvIGNhZGhlcmluLWJpbmRpbmcgbWF5IGJlIGEgZGlzdGluZ3Vpc2hhYmxlIGZ1bmN0aW9uYWwgZW5yaWNobWVudCBiZXR3ZWVuIGNsaW5pY2FsIHN1YnR5cGVzLS1idXQgdGhpcyBjbGFpbSBpcyB0b28gZ2VuZXJhbCB0byBjb25maWRlbnRseSBiYWNrLgoKSW50ZXJlc3RpbmdseSwgb25lIG9mIG91ciB0aHJlZSBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBnZW5lcyBhZnRlciBjb3JyZWN0aW9uIGFjcm9zcyBjbGluaWNhbCBzdWJ0eXBlcyBvZiBicmVhc3QgY2FuY2VyIGlzIGBBTlhBOGAgd2hpY2ggaXMgYXNzb2NpYXRlZCB3aXRoIGJyZWFzdCBjYW5jZXIgW0BtYWxhXS4gUm9zZXR0aSBldCBhbC4gc3VnZ2VzdGVkIGBBTlhBOGAgaXMgc2lnbmlmaWNhbnRseSBoaWdoZXIgaW4gYEVSLWAgc3VidHlwZXMgYXMgb3Bwb3NlZCB0byBgRVIrYCBzdWJ0eXBlcyBbQHJvc3NldHRpMjAxNmhhcm5lc3NpbmddIGJ1dCBpbnN0ZWFkIG9mIGZpbmRpbmcgdGhhdCBpbiBvdXIgcmVzdWx0cywgd2Ugbm90aWNlZCBgQU5YQThgIHdhcyBzaWduaWZpY2FudGx5IGRpZmZlcmVudGlhbGx5IGV4cHJlc3NlZCBhY3Jvc3MgYWxsIGNsaW5pY2FsIHN1YnR5cGVzIGNsYXNzaWZpZWQgaW4gb3VyIHN0dWR5IGFuZCBub3Qgc3BlY2lmaWNhbGx5IGBFUmAgb3ZlcmV4cHJlc3Npb24gb3IgbGFjayB0aGVyZW9mLiBUaGlzIHdhcnJhbnRzIGludmVzdGlnYXRpb24gaW50byB3aHkgYEFOWEE4YCBpcyBleHByZXNzZWQgZGlmZmVyZW50aWFsbHkgaW4gYEVSYCBzdWJ0eXBlcyBhY2NvcmRpbmcgdG8gcmVzZWFyY2gsIHlldCBzZWxlY3RpdmVseSBleHByZXNzZWQgZGlmZmVyZW50aWFsbHkgYWNyb3NzIGFsbCBmb3VyIG9mIG91ciBjbGFzc2lmaWVkIGNsaW5pY2FsIHN1YnR5cGVzIG9mIGJyZWFzdCBjYW5jZXIsIGFuZCBub3Qgc3BlY2lmaWNhbGx5IGZvciBgRVJgIGluLXNpbGljby4KCkluIHRlcm1zIG9mIHNpZ25pZmljYW50bHkgZGlmZmVyZW50aWFsbHkgZXhwcmVzc2VkIGdlbmVzIGluIHJlZ2FyZHMgdG8gYEVSLWAgYW5kIGBFUitgIHNwZWNpZmljYWxseSwgdGhlIG1vc3Qgc2lnbmlmaWNhbnQgZ2VuZSBpcyBgRVBIQTNgIHdoaWNoIGhhcyBiZWVuIHNob3duIHRvIGJlIGV4dGVuc2l2ZWx5IG1vcmUgdXAtcmVndWxhdGVkIGluIGBFUitgIGJyZWFzdCBjYW5jZXJzIFtAbGlhbmcyMDIxZXhwcmVzc2lvbl0sIHdoaWNoIGRpcmVjdGx5IHN1cHBvcnRzIG15IGZpbmRpbmdzLiBBbHRob3VnaCBteSBmaW5kaW5ncyB3ZXJlIG5vdCByZWZsZWN0aXZlIG9mIHRoZSBtZWNoYW5pc21zIGFuZCBkaXJlY3Rpb24gb2YgdGhlIHBhcGVyIEkgcmV0cmlldmVkIHRoZSBkYXRhIGZyb20sIHRoZXkgYXJlIHN1cHBvcnRlZCBieSBvdGhlciBldmlkZW5jZSBpbiBjZXJ0YWluIHdheXMuCgpJbiBjb25jbHVzaW9uLCB0aGVyZSBpcyBzb21lIGFzc29jaWF0ZWQgZXZpZGVuY2UgdGhhdCBzdWdnZXN0cyBteSByZXN1bHRzIGhhdmUgYSBmb3VuZGF0aW9uIGluIGZ1bmN0aW9uYWwgYmlvbG9neSwgaG93ZXZlciBub3RoaW5nIGhhcyBhIHNpZ25pZmljYW5jZSB0aGF0IHdvdWxkIGdpdmUgbWUgY29uZmlkZW5jZSB0byBiYWNrIG15IGNsYWltLiBGb3IgdGhpcywgSSB3b3VsZCB3YW50IGEgcC12YWx1ZSBzbWFsbGVyIHRoYW4gYDEwZS0zYC4KCiMgQWNrbm93bGVkZ21lbnRzCgpUaGlzIHBhcGVyIG1ha2VzIHVzZSBvZiBwYWNrYWdlcyBga25pdHJgIFtAa25pdHIyMDE1XSwgYEJpb2NNYW5hZ2VyYCBbQGJpb2NtYW5hZ2VyXSwgYEdFT3F1ZXJ5YCBbQFItR0VPcXVlcnldLCBga2FibGVFeHRyYWAgW0BrYWJsZWV4dHJhXSwgYGVkZ2VSYCBbQFItZWRnZVJdLCBgbGltbWFgIFtAbGltbWEyMDE1XSwgYENvbXBsZXhIZWF0bWFwYCBbQGNvbXBsZXhoZWF0bWFwXSwgYGNpcmNsaXplYCBbQGNpcmNsaXplXSwgYGdwcm9maWxlcjJgIFtAZ3Byb2ZpbGVyMl0sIGBHU0FgIFtAZ3NhXSwgJiBgZ2dwbG90MmAgW0BSLWdncGxvdDJdLgoKIyBCaWJsaW9ncmFwaHkK